angular.module('ui.grid')
.directive('uiGridCustomerColumnResizer', uiGridCustomerColumnResizer)
.directive('uiGridMenuCustomerButton', uiGridMenuCustomerButton)
.directive('uiGridCustomerMenuItem', uiGridCustomerMenuItem)
.directive('uiGridCustomerAutoResize', uiGridCustomerAutoResize)
.directive('uiGridCustomerPagination', uiGridCustomerPagination)
.service('uiGridOperationService', uiGridOperationService)
.directive('uiGridOperation', uiGridOperation)
.directive('uiGridOperationRowHeaderButtons', uiGridOperationRowHeaderButtons)
.directive('uiGridOperationHeaderButtons', uiGridOperationHeaderButtons)
.directive('uiGridEolOperation', uiGridEolOperation)
.directive('uiGridCustomerScrollbar', uiGridCustomerScrollbar)
.run(uiGridOperationTemplates);

uiGridCustomerScrollbar.$inject = [ '$timeout', '$parse', '$window', 'gridUtil', 'ScrollEvent', 'uiGridConstants' ];
function uiGridCustomerScrollbar($timeout, $parse, $window, gridUtil, ScrollEvent, uiGridConstants) {
	var uiGridCustomerScrollbarOptions = [ 'handlers', 'wheelSpeed', 'wheelPropagation', 'swipeEasing', 'minScrollbarLength', 'maxScrollbarLength', 'scrollingThreshold', 'useBothWheelAxes', 'suppressScrollX',
	                           			'suppressScrollY', 'scrollXMarginOffset', 'scrollYMarginOffset', ];
  return {
    priority: -200,
    transclude : true,
    replace : true,
    require: ['^uiGrid', '^uiGridRenderContainer'],
    template: '<div ng-transclude class="open" ng-click="clickEvent($event)"></div>',
    link: {
      pre: function ($scope, $elem, $attrs, controllers) {
    	    var jqWindow = angular.element($window);
			var options = {};
			var perfect;
			var uiGridCtrl = controllers[0];
			var grid = uiGridCtrl.grid;
	        var containerCtrl = controllers[1];
	        var rowContainer = containerCtrl.rowContainer;
	        var colContainer = containerCtrl.colContainer;
	        grid._scrollBars = grid._scrollBars || [];
	        $scope.scrollHandler = function(position) {
            	var newScrollTop = position.scrollTop;
            	var newScrollLeft = position.scrollLeft;//gridUtil.normalizeScrollLeft($elem, grid);
            	
            	var vertScrollPercentage = rowContainer.scrollVertical(newScrollTop);
            	var horizScrollPercentage = colContainer.scrollHorizontal(newScrollLeft);
            	
            	var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.ViewPortScroll);
            	scrollEvent.newScrollLeft = newScrollLeft;
            	scrollEvent.newScrollTop = newScrollTop;
            	if ( horizScrollPercentage > -1 ){
            		scrollEvent.x = { percentage: horizScrollPercentage };
            	}
            	
            	if ( vertScrollPercentage > -1 ){
            		scrollEvent.y = { percentage: vertScrollPercentage };
            	}
            	
            	grid.scrollContainers($scope.$parent.containerId, scrollEvent);
            	angular.forEach(grid._scrollBars, function(scrollbar){
            		if (perfect != scrollbar) {
            			scrollbar.lastScrollTop = perfect.lastScrollTop;
            			scrollbar.element.scrollLeft = perfect.element.scrollLeft;
            			
            			scrollbar.lastScrollLeft = perfect.lastScrollLeft;
            			scrollbar.element.scrollTop = perfect.element.scrollTop;
            			
            			scrollbar.onScroll();
            		}
            	});
	        }

			for (var i = 0, l = uiGridCustomerScrollbarOptions.length; i < l; i++) {
				var opt = uiGridCustomerScrollbarOptions[i];

				if ($attrs[opt] !== undefined) {
					options[opt] = $parse($attrs[opt])();
				}
			}
			
			if (grid.options.enableHorizontalScrollbar == 0) {
				options['suppressScrollX'] = true;
			}
			if (grid.options.enableVerticalScrollbar == 0) {
				options['suppressScrollY'] = true;
			}
			
			$scope.clickEvent = function($event) {
				var element = $event.srcElement || $event.target;
				element = angular.element(element);
				if(element && (element.hasClass('ps__rail-x') || element.hasClass('ps__rail-y') || element.hasClass('ps__thumb-x') || element.hasClass('ps__thumb-y'))){
					$event.stopPropagation();
				}
			};
			$scope.$evalAsync(function() {
				perfect = new PerfectScrollbar($elem[0], options);
				grid._scrollBars.push(perfect);
				var onScrollHandler = $parse($attrs.onScroll)($scope);
				var onScrollYEndHandler = $parse($attrs.onScrollYEnd)($scope);
				if (onScrollYEndHandler) {
					$elem.on('ps-y-reach-end', function() {
						var scrollTop = $elem.prop('scrollTop');
						var scrollHeight = $elem.prop('scrollHeight') - $elem[0].clientHeight;
						var scrollLeft = $elem.prop('scrollLeft');
						var scrollWidth = $elem.prop('scrollWidth') - $elem[0].clientWidth;
						
						onScrollYEndHandler({
							scrollTop : scrollTop,
							scrollHeight : scrollHeight,
							scrollLeft : scrollLeft,
							scrollWidth : scrollWidth
						});
					});
				}
				if (onScrollHandler) {
					var mouseWheeltoBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
					var renderContainer = angular.element($elem[0].parentElement.parentElement);
					angular.forEach(mouseWheeltoBind, function(bind){
						var cbs = renderContainer.data('mousewheel-callbacks');
						angular.forEach(cbs, function(fn){
							renderContainer.off(mouseWheeltoBind[--i], fn);
						});
					});
					$elem.on('scroll', function() {
						var scrollTop = $elem.prop('scrollTop');
						var scrollHeight = $elem.prop('scrollHeight') - $elem[0].clientHeight;
						var scrollLeft = $elem.prop('scrollLeft');
						var scrollWidth = $elem.prop('scrollWidth') - $elem[0].clientWidth;

						$scope.$apply(function() {
							onScrollHandler({
								scrollTop : scrollTop,
								scrollHeight : scrollHeight,
								scrollLeft : scrollLeft,
								scrollWidth : scrollWidth
							});
						});
					});
				}
			});

			// Automatically update when content height changes
			$scope.$watch(function() {
				return $elem.prop('scrollHeight');
			}, function(newValue, oldValue) {
				if (newValue) {
					update('contentSizeChange');
				}
			});
			$scope.$on('scrollbar-resize', function($event){
				perfect.update('mouseenter');
				$event.preventDefault();
				$event.stopPropagation();
			});
			function update(event) {
				$scope.$evalAsync(function() {
					if ($attrs.scrollDown == 'true' && event != 'mouseenter') {
						setTimeout(function() {
							$elem[0].scrollTop = $elem.prop("scrollHeight");
						}, 100);
					}

					perfect.update();
				});
			}

			// This is necessary when you don't watch anything with the scrollbar
			$elem.on('mouseenter', function() {
				update('mouseenter');
			});

			// Possible future improvement: check the type here and use the appropriate watch for non-arrays
			if ($attrs.refreshOnChange) {
				$scope.$watchCollection($attrs.refreshOnChange, function() {
					update();
				});
			}

			// Rebuild on window resize
			if ($attrs.refreshOnResize) {
				jqWindow.on('resize', function() {
					update();
				});
			}

			if ($attrs.updateOn) {
				$attrs.updateOn.split(' ').forEach(function(eventName) {
					$scope.$on(eventName, update);
				});
			}

			// Unbind resize event and destroy instance
			$elem.on('$destroy', function() {
				$elem.off();
				jqWindow.off('resize', function() {
					update();
				});
				if (perfect) {
					perfect.destroy();
					perfect = null;
				}
			});
      }
    }
  };
}

uiGridCustomerColumnResizer.$inject = [ '$document', 'gridUtil', 'uiGridConstants', 'uiGridResizeColumnsService', '$injector' ];
function uiGridCustomerColumnResizer($document, gridUtil, uiGridConstants, uiGridResizeColumnsService, $injector) {//change db click logic
    var resizeOverlay = angular.element('<div class="ui-grid-resize-overlay"></div>');

    var resizer = {
      priority: 0,
      scope: {
        col: '=',
        position: '@',
        renderIndex: '='
      },
      require: '?^uiGrid',
      link: function ($scope, $elm, $attrs, uiGridCtrl) {
        var startX = 0,
            x = 0,
            gridLeft = 0,
            rtlMultiplier = 1;

        //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left
        if (uiGridCtrl.grid.isRTL()) {
          $scope.position = 'left';
          rtlMultiplier = -1;
        }

        if ($scope.position === 'left') {
          $elm.addClass('left');
        }
        else if ($scope.position === 'right') {
          $elm.addClass('right');
        }

        // Refresh the grid canvas
        //   takes an argument representing the diff along the X-axis that the resize had
        function refreshCanvas(xDiff) {
          // Then refresh the grid canvas, rebuilding the styles so that the scrollbar updates its size
          uiGridCtrl.grid.refreshCanvas(true).then( function() {
            uiGridCtrl.grid.queueGridRefresh();
          });
        }

        // Check that the requested width isn't wider than the maxWidth, or narrower than the minWidth
        // Returns the new recommended with, after constraints applied
        function constrainWidth(col, width){
          var newWidth = width;

          // If the new width would be less than the column's allowably minimum width, don't allow it
          if (col.minWidth && newWidth < col.minWidth) {
            newWidth = col.minWidth;
          }
          else if (col.maxWidth && newWidth > col.maxWidth) {
            newWidth = col.maxWidth;
          }

          return newWidth;
        }


        /*
         * Our approach to event handling aims to deal with both touch devices and mouse devices
         * We register down handlers on both touch and mouse.  When a touchstart or mousedown event
         * occurs, we register the corresponding touchmove/touchend, or mousemove/mouseend events.
         *
         * This way we can listen for both without worrying about the fact many touch devices also emulate
         * mouse events - basically whichever one we hear first is what we'll go with.
         */
        function moveFunction(event, args) {
          if (event.originalEvent) { event = event.originalEvent; }
          event.preventDefault();

          x = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;

          if (x < 0) { x = 0; }
          else if (x > uiGridCtrl.grid.gridWidth) { x = uiGridCtrl.grid.gridWidth; }

          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);

          // Don't resize if it's disabled on this column
          if (col.colDef.enableColumnResizing === false) {
            return;
          }

          if (!uiGridCtrl.grid.element.hasClass('column-resizing')) {
            uiGridCtrl.grid.element.addClass('column-resizing');
          }

          // Get the diff along the X axis
          var xDiff = x - startX;

          // Get the width that this mouse would give the column
          var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);

          // check we're not outside the allowable bounds for this column
          x = x + ( constrainWidth(col, newWidth) - newWidth ) * rtlMultiplier;

          resizeOverlay.css({ left: x + 'px' });

          uiGridCtrl.fireEvent(uiGridConstants.events.ITEM_DRAGGING);
        }


        function upFunction(event, args) {
          if (event.originalEvent) { event = event.originalEvent; }
          event.preventDefault();

          uiGridCtrl.grid.element.removeClass('column-resizing');

          resizeOverlay.remove();

          // Resize the column
          x = (event.changedTouches ? event.changedTouches[0] : event).clientX - gridLeft;
          var xDiff = x - startX;

          if (xDiff === 0) {
            // no movement, so just reset event handlers, including turning back on both
            // down events - we turned one off when this event started
            offAllEvents();
            onDownEvents();
            return;
          }

          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);

          // Don't resize if it's disabled on this column
          if (col.colDef.enableColumnResizing === false) {
            return;
          }

          // Get the new width
          var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);

          // check we're not outside the allowable bounds for this column
          col.width = constrainWidth(col, newWidth);
          col.hasCustomWidth = true;

          refreshCanvas(xDiff);

          uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);

          // stop listening of up and move events - wait for next down
          // reset the down events - we will have turned one off when this event started
          offAllEvents();
          onDownEvents();
        }


        var downFunction = function(event, args) {
          if (event.originalEvent) { event = event.originalEvent; }
          event.stopPropagation();

          // Get the left offset of the grid
          // gridLeft = uiGridCtrl.grid.element[0].offsetLeft;
          gridLeft = uiGridCtrl.grid.element[0].getBoundingClientRect().left;

          // Get the starting X position, which is the X coordinate of the click minus the grid's offset
          startX = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;

          // Append the resizer overlay
          uiGridCtrl.grid.element.append(resizeOverlay);

          // Place the resizer overlay at the start position
          resizeOverlay.css({ left: startX });

          // Add handlers for move and up events - if we were mousedown then we listen for mousemove and mouseup, if
          // we were touchdown then we listen for touchmove and touchup.  Also remove the handler for the equivalent
          // down event - so if we're touchdown, then remove the mousedown handler until this event is over, if we're
          // mousedown then remove the touchdown handler until this event is over, this avoids processing duplicate events
          if ( event.type === 'touchstart' ){
            $document.on('touchend', upFunction);
            $document.on('touchmove', moveFunction);
            $elm.off('mousedown', downFunction);
          } else {
            $document.on('mouseup', upFunction);
            $document.on('mousemove', moveFunction);
            $elm.off('touchstart', downFunction);
          }
        };

        var onDownEvents = function() {
          $elm.on('mousedown', downFunction);
          $elm.on('touchstart', downFunction);
        };

        var offAllEvents = function() {
          $document.off('mouseup', upFunction);
          $document.off('touchend', upFunction);
          $document.off('mousemove', moveFunction);
          $document.off('touchmove', moveFunction);
          $elm.off('mousedown', downFunction);
          $elm.off('touchstart', downFunction);
        };

        onDownEvents();


        // On doubleclick, resize to fit all rendered cells
        var dblClickFn = function(event, args){
          event.stopPropagation();

          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);

          // Don't resize if it's disabled on this column
          if (col.colDef.enableColumnResizing === false) {
            return;
          }
          var storageService = $injector.get('storageService');
          var setting = storageService.getTableSetting(($scope.$root.pageId+':'+uiGridCtrl.grid.options.name).split('.').join('_')) || {};
          var newWidth = setting.width[col.field] ? setting.width[col.field].width : col.drawnWidth;
          xDiff = newWidth - col.drawnWidth;
          col.width = newWidth;
          col.hasCustomWidth = true;

          refreshCanvas(xDiff);

          uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);        };
        $elm.on('dblclick', dblClickFn);

        $elm.on('$destroy', function() {
          $elm.off('dblclick', dblClickFn);
          offAllEvents();
        });
      }
    };

    return resizer;
}

uiGridMenuCustomerButton.$inject = [ 'gridUtil', 'uiGridConstants', 'uiGridGridMenuService', 'i18nService', '$timeout', '$injector' ];
function uiGridMenuCustomerButton(gridUtil, uiGridConstants, uiGridGridMenuService, i18nService, $timeout, $injector) {//add show all and normal
	return {
		priority: 0,
		scope: true,
		require: ['^uiGrid'],
		templateUrl: 'ui-grid/ui-grid-menu-button',
		replace: true,
	
		link: function ($scope, $elm, $attrs, controllers) {
			var uiGridCtrl = controllers[0], storageService = $injector.get('storageService');
		
			// For the aria label
			$scope.i18n = {
				aria: i18nService.getSafeText('gridMenu.aria')
			};
		
			uiGridGridMenuService.initialize($scope, uiGridCtrl.grid);
			uiGridCtrl.grid.options.displayStyle = uiGridCtrl.grid.options.displayStyle || 'normal';
			if (uiGridCtrl.grid.api.colResizable) {
				uiGridCtrl.grid.api.colResizable.on.columnSizeChanged($scope,function(colDef, deltaChange){
					 if (storageService) {
		            	  var setting = storageService.getTableSetting(($scope.$root.pageId+':'+uiGridCtrl.grid.options.name).split('.').join('_')) || {};
		            	  var column;
		            	  for (i =0; i < uiGridCtrl.grid.columns.length; i++) {
		            		  if (uiGridCtrl.grid.columns[i].field == colDef.field) {
		            			  column = uiGridCtrl.grid.columns[i];
		            			  break;
		            		  }
		            	  }
		            	  setting.width = setting.width || {};
		            	  if (!setting.width[colDef.field]) {
		            		  setting.width[colDef.field] = {
		            			  width: colDef.width,
		            			  minWidth:colDef.minWidth
		            		  };
		            	  }
		            	  setting.width['_'+uiGridCtrl.grid.options.displayStyle] = setting.width['_'+uiGridCtrl.grid.options.displayStyle] || {};
		            	  setting.width['_'+uiGridCtrl.grid.options.displayStyle][colDef.field] = setting.width['_'+uiGridCtrl.grid.options.displayStyle][colDef.field] || {};
		            	  setting.width['_'+uiGridCtrl.grid.options.displayStyle][colDef.field].adjustWidth = column.width;
		            	  storageService.saveTableSetting(($scope.$root.pageId+':'+uiGridCtrl.grid.options.name).split('.').join('_'), setting);
		              }
				});
			}
			$scope.shown = false;
			$scope.toggleDisplayStyle = function() {
				if ($scope.switchChecked) {
					uiGridCtrl.grid.options.displayStyle = 'all';
					$scope.showAll();
				} else {
					uiGridCtrl.grid.options.displayStyle = 'normal'
					$scope.showNormal();
				}
			};
			$scope.showAll = function() {
				var tableSetting, originalSetting, needSaveSetting;
				tableSetting = storageService.getTableSetting(($scope.$root.pageId+':'+uiGridCtrl.grid.options.name).split('.').join('_'));
				angular.forEach(uiGridCtrl.grid.columns, function(column, index) {
					if (column.field && column.field.indexOf('RowHeaderCol') < 0) {
						if (tableSetting && tableSetting.width && tableSetting.width[column.field]) {
							originalSetting = tableSetting.width[column.field];
						} else if(column.colDef.minWidth || column.colDef.width) {
							needSaveSetting = true;
							tableSetting = tableSetting || {};
							originalSetting = tableSetting[column.colDef.field] = {
								width: column.colDef.width || column.width,
								minWidth:column.colDef.minWidth
							};
						}
						if (tableSetting && tableSetting.width && tableSetting.width['_'+uiGridCtrl.grid.options.displayStyle] && tableSetting.width['_'+uiGridCtrl.grid.options.displayStyle][column.field]) {
							column.width = tableSetting.width['_'+uiGridCtrl.grid.options.displayStyle][column.field].adjustWidth;
						} else {
							column.width = '*';
						}
						column.minWidth = column.colDef.minWidth ? 30 : null;
					}
				});
				if (needSaveSetting) {
					storageService.saveTableSetting(($scope.$root.pageId+':'+uiGridCtrl.grid.options.name).split('.').join('_'), {
						width: tableSetting
					});
				}
				uiGridCtrl.grid.refreshCanvas(true).then(function(){
					angular.forEach(uiGridCtrl.grid._scrollBars, function(scrollbar){
						scrollbar.update();
					});
				});
			};
			$scope.showNormal = function() {
				var tableSetting, originalSetting;
				tableSetting = storageService.getTableSetting(($scope.$root.pageId+':'+uiGridCtrl.grid.options.name).split('.').join('_'));
				angular.forEach(uiGridCtrl.grid.columns, function(column) {
					if (column.field && column.name.indexOf('RowHeaderCol') < 0) {
						if (tableSetting && tableSetting.width && tableSetting.width[column.field]) {
							originalSetting = tableSetting.width[column.field];
						}
						if (tableSetting && tableSetting.width && tableSetting.width['_'+uiGridCtrl.grid.options.displayStyle] && tableSetting.width['_'+uiGridCtrl.grid.options.displayStyle][column.field]) {
							column.colDef.width = tableSetting.width['_'+uiGridCtrl.grid.options.displayStyle][column.field].adjustWidth;
						} else if (originalSetting) {
							column.colDef.width = originalSetting.width;
						}
						column.colDef.minWidth = originalSetting ? originalSetting.minWidth : column.colDef.minWidth;
					}
				});
				uiGridCtrl.grid.refreshCanvas(true).then(function(){
					angular.forEach(uiGridCtrl.grid._scrollBars, function(scrollbar){
						scrollbar.update('mouseenter');
					});
				});
				uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
			};
			$scope.toggleMenu = function () {
				if ($scope.shown){
					$scope.$broadcast('hide-menu');
					$scope.shown = false;
				} else {
					$scope.menuItems = uiGridGridMenuService.getMenuItems( $scope );
					$scope.$broadcast('show-menu');
					$scope.shown = true;
				}
			};
		
			$scope.$on('menu-hidden', function() {
				$scope.shown = false;
				gridUtil.focus.bySelector($elm, '.ui-grid-icon-container');
			});
			function gridResize() {
	        	uiGridCtrl.grid.gridWidth = gridUtil.elementWidth($elm);
				uiGridCtrl.grid.gridHeight = gridUtil.elementHeight($elm);
				uiGridCtrl.grid.refreshCanvas(true);
	        }
		}
	};
}

uiGridCustomerMenuItem.$inject = [ 'gridUtil', '$compile', 'i18nService', 'uiGridMoveColumnService', 'uiGridResizeColumnsService', '$injector' ];
function uiGridCustomerMenuItem(gridUtil, $compile, i18nService, uiGridMoveColumnService, uiGridResizeColumnsService, $injector) { // change menu items
	return {
	    priority: 0,
	    scope: {
	      name: '=',
	      active: '=',
	      action: '=',
	      icon: '=',
	      shown: '=',
	      context: '=',
	      templateUrl: '=',
	      leaveOpen: '=',
	      screenReaderOnly: '=',
	      index:'='
	    },
	    require: ['?^uiGrid'],
	    templateUrl: 'ui-grid/uiGridMenuItem',
	    replace: false,
	    compile: function() {
	      return {
	        pre: function ($scope, $elm) {
	          if ($scope.templateUrl) {
	            gridUtil.getTemplate($scope.templateUrl)
	                .then(function (contents) {
	                  var template = angular.element(contents);

	                  var newElm = $compile(template)($scope);
	                  $elm.replaceWith(newElm);
	                }).catch(angular.noop);
	          }
	        },
	        post: function ($scope, $elm, $attrs, controllers) {
	          var uiGridCtrl = controllers[0];
	          
	          $scope.getGrid = function() {
	        	  return uiGridCtrl.grid;
	          };

	          // TODO(c0bra): validate that shown and active are functions if they're defined. An exception is already thrown above this though
	          // if (typeof($scope.shown) !== 'undefined' && $scope.shown && typeof($scope.shown) !== 'function') {
	          // throw new TypeError("$scope.shown is defined but not a function");
	          // }
	          if (typeof($scope.shown) === 'undefined' || $scope.shown === null) {
	            $scope.shown = function() { return true; };
	          }

	          $scope.visible = $scope.context ? $scope.context.gridCol.colDef.visible : undefined;
	          
	          $scope.itemShown = function () {
	            var context = {};
	            if ($scope.context) {
	              context.context = $scope.context;
	            }

	            if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {
	              context.grid = uiGridCtrl.grid;
	            }

	            return $scope.shown.call(context);
	          };

	          $scope.itemAction = function($event,title) {
	            $event.stopPropagation();

	            if (typeof($scope.action) === 'function') {
	              var context = {};

	              if ($scope.context) {
	                context.context = $scope.context;
	              }

	              // Add the grid to the function call context if the uiGrid controller is present
	              if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {
	                context.grid = uiGridCtrl.grid;
	              }
	              adjustColumnWidth();
	              $scope.visible = $scope.context.gridCol.colDef.visible;
	              if ($injector.get('storageService')) {
	            	  var visible = {};
	            	  visible[$scope.context.gridCol.colDef.field] = $scope.context.gridCol.colDef.visible;
	            	  $injector.get('storageService').saveTableSetting(($scope.$root.pageId+':'+uiGridCtrl.grid.options.name).split('.').join('_'), {
	            		  'visible':visible
	            	  });
	              }
	              $scope.$emit('hide-column');
	              if ( !$scope.leaveOpen ){
	                $scope.$emit('hide-menu');
	              } else {
	                // Maintain focus on the selected item
	            	/*var correctParent = $event.target.parentElement;

	                // nodeName of 'I' means target is i element, need the next parent
	                if (angular.element($event.target)[0].nodeName === 'I') {
	                  correctParent = correctParent.parentElement;
	                }

	                gridUtil.focus.bySelector(correctParent, 'button[type=button]', true);*/
	              }
	            }
	          };
	          
	          $scope.itemMoved = function($event) {
	        	  var i, col, columns;
	        	  col =  $scope.context.gridCol.colDef;
	        	  columns = uiGridCtrl.grid.columns;
	        	  if ((angular.isUndefined(col.visible) || col.visible === true)) {
	        		  for (i = 0; i < columns.length; i++) {
	                        if ((angular.isUndefined(columns[i].colDef.visible) || columns[i].colDef.visible === true) && $scope.context.gridCol.uid == columns[i].uid) {
	                            uiGridMoveColumnService.redrawColumnAtPosition(uiGridCtrl.grid, i, i - 1);
	                            break;
	                        }
	                  }
	        		  uiGridMoveColumnService(uiGridCtrl.grid, index, index - 1);
	        	  }
	          }

	          $scope.label = function(){
	            var toBeDisplayed = $scope.name;

	            if (typeof($scope.name) === 'function'){
	              toBeDisplayed = $scope.name.call();
	            }

	            return toBeDisplayed;
	          };

	          $scope.i18n = i18nService.get();
	          
	          function adjustColumnWidth() {
	              //TODU:
	          }
	        }
	      };
	    }
	}
}
uiGridCustomerAutoResize.$inject = [ 'gridUtil', 'uiGridConstants', '$interval', '$timeout', '$window', '$document', 'ScrollEvent' ];
function uiGridCustomerAutoResize(gridUtil, uiGridConstants, $interval, $timeout, $window, $document, ScrollEvent) {
    return {
      require: 'uiGrid',
      scope: false,
      link: function($scope, $elm, $attrs, uiGridCtrl) {
        var watch, cellsWatch, watchers = [];
        ScrollEvent.prototype.atTop = function(scrollTop) {
        	var viewport = $elm[0].querySelector('.ui-grid-render-container-body .ui-grid-viewport');
        	if (viewport && angular.element(viewport).css('overflow-y') == 'hidden') {
        		return true;
        	}
    		return (this.y && (this.y.percentage === 0 || this.verticalScrollLength < 0) && scrollTop === 0);
    	};
    	ScrollEvent.prototype.atBottom = function(scrollTop) {
    		var viewport = $elm[0].querySelector('.ui-grid-render-container-body .ui-grid-viewport');
    		if (viewport && angular.element(viewport).css('overflow-y') == 'hidden') {
        		return true;
        	}
    		return (this.y && (this.y.percentage === 1 || this.verticalScrollLength === 0) && scrollTop > 0);
    	};
        scrollbarWidth = gridUtil.getScrollbarWidth();
        $scope.$on('$destroy', function() {
        	(cellsWatch || angular.noop)();
			while (watchers.length) {
				(watchers.shift() || angular.noop)();
			}
		});
        watch = $scope.$watchGroup([function(){
        	var bodyWidth = gridUtil.elementWidth($document[0].querySelector('body'));
        	return  $window.innerWidth - bodyWidth;
        }], function(newValues, oldValues) {
        	if (!angular.equals(newValues, oldValues)) {
        		gridResize();
        	}
        });
        watchers.push(watch);
        angular.element($window).on('resize', function(){
        	var timer;
			timer = $interval(function() {
				var adjustRows = autoAdjustHeight();
				if (uiGridCtrl.grid.renderContainers.body.renderedRows.length >  0 && adjustRows == uiGridCtrl.grid.renderContainers.body.renderedRows.length) {
					$interval.cancel(timer);
				} else if (!uiGridCtrl.grid.renderContainers.body.renderedRows || uiGridCtrl.grid.renderContainers.body.renderedRows.length ==  0) {
					$interval.cancel(timer);
				}
			}, 200, false);
        });
        watch = $scope.$watchCollection(function(){return uiGridCtrl.grid.renderContainers.body.renderedRows;}, adjustHeight);
        watchers.push(watch);
       /* $scope.$on('hide-column', function (event, args) {
        	adjustHeight(uiGridCtrl.grid.renderContainers.body.renderedRows);
        	event.preventDefault();
			event.stopPropagation();
        });*/
        function adjustHeight(newData, oldData) {
        	var timer;
			timer = $interval(function() {
				var adjustRows = autoAdjustHeight();
				if (newData && newData.length >  0 && adjustRows == newData.length) {
					$interval.cancel(timer);
				} else if (!newData || newData.length ==  0) {
					$interval.cancel(timer);
				}
			}, 200, false);
        }
        function autoAdjustHeight() {
        	var leftCanvas, centerCanvas, rightCanvas, leftRows, centerRows, rightRows, leftGridCanvas, centerGridCanvas, rightGridCanvas, gridViewports, gridColumnFooter, gridFooter, pageBar;
        	var i, e1, e2, e3, cells, cellsWatchGroup, visibleLines = 0,maxHeight, scrollbarHeight = 0, contentHeight = 0, headerHeight = 0, footerHeight = 0,scrollbarHeight = 0, filterHeight = 0, pageBarHeight = 0, maxNumberOfFilters = 0, allColumnsHaveFilteringTurnedOff;
        	var adjustElements = [];
        	if (uiGridCtrl.grid.options.showHeader) {
        		e1 = $elm[0].querySelector(".ui-grid-render-container-left .ui-grid-header-cell-wrapper");
        		e2 = $elm[0].querySelector(".ui-grid-render-container-body .ui-grid-header-cell-wrapper");
        		e3 = $elm[0].querySelector(".ui-grid-render-container-right .ui-grid-header-cell-wrapper");
        		leftCanvas = $elm[0].querySelector(".ui-grid-render-container-left .ui-grid-header-canvas");
        		centerCanvas = $elm[0].querySelector(".ui-grid-render-container-body .ui-grid-header-canvas");
        		rightCanvas = $elm[0].querySelector(".ui-grid-render-container-right .ui-grid-header-canvas");
        		
        		maxHeight = uiGridCtrl.grid.options.headerRowHeight;
        		if (e1) {
					angular.element(e1).css({height : 'auto'});
				}
        		if (e2) {
					angular.element(e2).css({height : 'auto'});
					cells = e2.querySelectorAll('.ui-grid-header-cell');
					if(cells && cells.length > 0){
						cellsWatchGroup = [];
						angular.forEach(cells, function(cell, i){
							cellsWatchGroup[i] = function(){
								return cell.offsetWidth;
							}
						});
						(cellsWatch || angular.noop)();
						cellsWatch = $scope.$watchGroup(cellsWatchGroup, function(newValues, oldValues) {
							if (!angular.equals(newValues, oldValues)) {
								adjustHeight(uiGridCtrl.grid.renderContainers.body.renderedRows);
							}
						});
					}
				}
				if (e3) {
					angular.element(e3).css({height : 'auto'});
				}
				if (leftCanvas ) {
        			angular.element(leftCanvas).css({ height : 'auto' });
        		}
        		if (centerCanvas) {
        			angular.element(centerCanvas).css({ height : 'auto' });
        		}
        		if (rightCanvas) {
        			angular.element(rightCanvas).css({ height : 'auto' });
        		}
        		maxHeight = Math.max(maxHeight, e1 ? e1.offsetHeight : 0, e2 ? e2.offsetHeight : 0, e3 ? e3.offsetHeight : 0);
        		headerHeight += maxHeight;
        		if (e1) {
        			angular.element(e1).css({ height : maxHeight + 'px' });
        		}
        		if (e2) {
        			angular.element(e2).css({ height : maxHeight + 'px' });
        		}
        		if (e3) {
        			angular.element(e3).css({ height : maxHeight + 'px' });
        		}
        		/*if (leftCanvas) {
        			angular.element(leftCanvas).css({ height : headerHeight + 'px' });
        		}
        		if (centerCanvas) {
        			angular.element(centerCanvas).css({ height : headerHeight + 'px' });
        		}
        		if (rightCanvas) {
        			angular.element(rightCanvas).css({ height : headerHeight + 'px' });
        		}*/
        	}
        	gridViewports = $elm[0].querySelectorAll('.ui-grid-viewport');
        	if (!gridViewports || gridViewports.length == 0) {
        		return 0;
        	}
			leftGridCanvas = $elm[0].querySelector(".ui-grid-render-container-left .ui-grid-viewport .ui-grid-canvas");
			centerGridCanvas = $elm[0].querySelector(".ui-grid-render-container-body .ui-grid-viewport .ui-grid-canvas");
			rightGridCanvas = $elm[0].querySelector(".ui-grid-render-container-right .ui-grid-viewport .ui-grid-canvas");
			leftRows = leftGridCanvas ? leftGridCanvas.querySelectorAll(".grid-row"): undefined;
			centerRows = centerGridCanvas ? centerGridCanvas.querySelectorAll(".grid-row") : undefined;
			rightRows = rightGridCanvas? rightGridCanvas.querySelectorAll(".grid-row") : undefined;
			for (i = 0; centerRows && i < centerRows.length; i++) {
				e1 = leftRows ? leftRows[i] : undefined;
				e2 = centerRows ? centerRows[i] : undefined;
				e3 = rightRows ? rightRows[i] : undefined;
				maxHeight = uiGridCtrl.grid.options.rowHeight;
				if (e1) {
					angular.element(e1).css({height : 'auto'});
				}
				if (e2) {
					angular.element(e2).css({height : 'auto'});
				}
				if (e3) {
					angular.element(e3).css({height : 'auto'});
				}
				maxHeight = Math.max(maxHeight, e1 ? e1.offsetHeight : 0, e2 ? e2.offsetHeight : 0, e3 ? e3.offsetHeight : 0);
				if (uiGridCtrl.grid.options.maxRowsToShow > 0) {
					if (i < uiGridCtrl.grid.options.maxRowsToShow) {
						visibleLines++;
						contentHeight += maxHeight;
					}
				} else if (i < uiGridCtrl.grid.options.paginationPageSize || uiGridCtrl.grid.options.enableVerticalScrollbar == uiGridConstants.scrollbars.NEVER){
					visibleLines++;
					contentHeight += maxHeight;
				}
				if (e1) {
					adjustElements.push({element:angular.element(e1), height: maxHeight});
				}
				if (e2) {
					adjustElements.push({element:angular.element(e2), height: maxHeight});
				}
				if (e3) {
					adjustElements.push({element:angular.element(e3), height: maxHeight});
				}
			}
			
			angular.forEach(adjustElements, function(elm, height){
				elm.element.css({height : elm.height + 'px'});
			});
			
			if (!contentHeight) {
				angular.element(centerGridCanvas).css({
						height : uiGridCtrl.grid.options.rowHeight + 'px'
					});
			} else {
				angular.element(centerGridCanvas).css({
					height : 'auto'
				});
			}
			
			contentHeight = contentHeight ? contentHeight : uiGridCtrl.grid.options.rowHeight;
			contentHeight += (visibleLines ? visibleLines : 0);
			footerHeight = uiGridCtrl.grid.calcFooterHeight();
			if (needsHScrollbarPlaceholder()) {
				scrollbarHeight = uiGridCtrl.grid.scrollbarHeight;
			}
			if ($elm[0].querySelector(".ui-grid-render-container-body .ui-grid-viewport .ps__thumb-x") && $elm[0].querySelector(".ui-grid-render-container-body .ui-grid-viewport .ps__thumb-x").offsetHeight > 0) {
				contentHeight += $elm[0].querySelector(".ui-grid-render-container-body .ui-grid-viewport .ps__thumb-x").offsetHeight + 2;
			}
			angular.forEach(uiGridCtrl.grid.options.columnDefs, function(col) {
				if (col.hasOwnProperty('filter')) {
					if (maxNumberOfFilters < 1) {
						maxNumberOfFilters = 0;
					}
				} else if (col.hasOwnProperty('filters')) {
					if (maxNumberOfFilters < col.filters.length) {
						maxNumberOfFilters = col.filters.length;
					}
				}
			});
			
			if (uiGridCtrl.grid.options.enableFiltering  && !maxNumberOfFilters) {
				allColumnsHaveFilteringTurnedOff = uiGridCtrl.grid.options.columnDefs.length && uiGridCtrl.grid.options.columnDefs.every(function(col) {
					return col.enableFiltering === false;
				});
				if (!allColumnsHaveFilteringTurnedOff) {
					maxNumberOfFilters = 1;
				}
			}
			
			filterHeight = maxNumberOfFilters * ( uiGridCtrl.grid.options.showHeader ? uiGridCtrl.grid.options.headerRowHeight : 0);
			
			pageBar = $elm[0].querySelector(".ui-grid-pager-panel");
			if(pageBar){
				pageBarHeight = gridUtil.elementHeight(angular.element(pageBar));
			}
			//var h = headerHeight + contentHeight + footerHeight + scrollbarHeight + filterHeight + pageBarHeight;
			var gridViewport = $elm[0].querySelector(".ui-grid-render-container-left .ui-grid-viewport");
			if (gridViewport && angular.element(gridViewport).css("height") != (contentHeight + 'px')) {
				angular.element(gridViewport).css({height : contentHeight + 'px'});
				angular.element(gridViewport.querySelector(".scroller")).css({height : contentHeight + 'px'});
			}
			gridViewport = $elm[0].querySelector(".ui-grid-render-container-body .ui-grid-viewport");
			if (gridViewport && angular.element(gridViewport).css("height") != ((contentHeight + scrollbarHeight) + 'px')) {
				angular.element(gridViewport).css({height : (contentHeight + scrollbarHeight) + 'px'});
				angular.element(gridViewport.querySelector(".scroller")).css({height : (contentHeight + scrollbarHeight) + 'px'});
				$scope.$broadcast('scrollbar-resize');
			}
			gridViewport = $elm[0].querySelector(".ui-grid-render-container-right .ui-grid-viewport");
			if (gridViewport && angular.element(gridViewport).css("height") != (contentHeight + 'px')) {
				angular.element(gridViewport).css({height : contentHeight + 'px'});
				angular.element(gridViewport.querySelector(".scroller")).css({height : contentHeight + 'px'});
			}
			
			/*if (uiGridCtrl.grid.options.enablePagination && uiGridCtrl.grid.options.enablePaginationControls) {
				h += (visibleLines ? visibleLines : 0);
			}*/
			if ($elm.css("height") != 'auto') {
				$elm.css('height', 'auto');
			}
			$timeout(function(){
				gridResize();
			}, 200);
			
			return centerRows ? centerRows.length : 0;
		}
        
        function gridResize() {
        	uiGridCtrl.grid.gridWidth = gridUtil.elementWidth($elm);
			uiGridCtrl.grid.gridHeight = gridUtil.elementHeight($elm);
			uiGridCtrl.grid.refreshCanvas(true);
        }
        
        function needsHScrollbarPlaceholder() {
        	var self = uiGridCtrl, containerBody;
			if (self.grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
				return true;
			}
			containerBody = $elm[0].querySelector('.ui-grid-render-container-body .ui-grid-viewport');
			return containerBody.scrollWidth > containerBody.offsetWidth;
    	}
      }
    };
}

uiGridCustomerPagination.$inject = [ 'gridUtil', 'uiGridPaginationService' ];
function uiGridCustomerPagination(gridUtil, uiGridPaginationService) {
  return {
    priority: -200,
    scope: false,
    require: 'uiGrid',
    link: {
      pre: function ($scope, $elm, $attr, uiGridCtrl) {
        uiGridPaginationService.initializeGrid(uiGridCtrl.grid);

        gridUtil.getTemplate(uiGridCtrl.grid.options.paginationTemplate)
          .then(function (contents) {
			var template = angular.element(contents);
			if (uiGridCtrl.grid.options.paginationStyle == 'before') {
				$elm.prepend(template);
			}
			if (!uiGridCtrl.grid.options.paginationStyle || uiGridCtrl.grid.options.paginationStyle == 'after') {
				$elm.append(template);
			}
            uiGridCtrl.innerCompile(template);
          });
      }
    }
  };
}

uiGridOperationService.$inject = [ '$q', '$templateCache', 'uiGridSelectionConstants', 'gridUtil' ];
function uiGridOperationService($q, $templateCache, uiGridSelectionConstants, gridUtil) {
	var service = {
		initializeGrid : function(grid) {
			service.defaultGridOptions(grid.options);
		},
		defaultGridOptions : function(gridOptions) {
			gridOptions.enableOperation = gridOptions.enableOperation == true;
			gridOptions.enableOperationAdd = gridOptions.addRow ? true : false;
			gridOptions.enableOperationRemoveSelected = gridOptions.enableOperationRemoveSelected !== false;
			gridOptions.enableOperationRemoveAll = gridOptions.enableOperationRemoveAll !== false;
			gridOptions.enableOperationView = gridOptions.viewRow ? true : false;
			gridOptions.enableOperationEdit = gridOptions.editRow ? true : false;
			gridOptions.enableOperationCancel = gridOptions.cancelRow ? true : false;
			gridOptions.enableOperationAddSubRow = gridOptions.addSubRow ? true : false;
			gridOptions.enableOperationRemove = gridOptions.removeRow ? true : false;
			gridOptions.enableOperationProcess = gridOptions.processRow ? true : false;
			gridOptions.enableOperationMoreProcess = gridOptions.moreProcess ? true : false;
			gridOptions.viewRowPermission = gridOptions.viewRowPermission ? gridOptions.viewRowPermission : "*";
			gridOptions.editRowPermission = gridOptions.editRowPermission ? gridOptions.editRowPermission : "*";
			gridOptions.cancelRowPermission = gridOptions.cancelRowPermission ? gridOptions.cancelRowPermission : "*";
			gridOptions.downloadRowPermission = gridOptions.downloadRowPermission ? gridOptions.downloadRowPermission : "*";
			gridOptions.addSubRowPermission = gridOptions.addSubRowPermission ? gridOptions.addSubRowPermission : "*";
			gridOptions.removeRowPermission = gridOptions.removeRowPermission ? gridOptions.removeRowPermission : "*";
			gridOptions.processRowPermission = gridOptions.processRowPermission ? gridOptions.processRowPermission : "*";
			
			gridOptions.enableEolOperation = gridOptions.enableEolOperation == true;
			gridOptions.enableEolOperationView = gridOptions.viewRowByEol ? true : false;
			gridOptions.enableEolOperationEdit = gridOptions.editRowByEol ? true : false;
			gridOptions.enableEolOperationCancel = gridOptions.cancelRowByEol ? true : false;
			gridOptions.enableEolOperationDownload = gridOptions.downloadRowByEol ? true : false;
			gridOptions.enableEolOperationAddSubRow = gridOptions.addSubRowByEol ? true : false;
			gridOptions.enableEolOperationRemove = gridOptions.removeRowByEol ? true : false;
			gridOptions.enableEolOperationProcess = gridOptions.processRowByEol ? true : false;
			gridOptions.enableEolOperationMoreProcess = gridOptions.moreProcessByEol ? true : false;
			gridOptions.viewRowByEolPermission = gridOptions.viewRowByEolPermission ? gridOptions.viewRowByEolPermission : "*";
			gridOptions.editRowByEolPermission = gridOptions.editRowByEolPermission ? gridOptions.editRowByEolPermission : "*";
			gridOptions.cancelRowByEolPermission = gridOptions.cancelRowByEolPermission ? gridOptions.cancelRowByEolPermission : "*";
			gridOptions.downloadRowByEolPermission = gridOptions.downloadRowByEolPermission ? gridOptions.downloadRowByEolPermission : "*";
			gridOptions.addSubRowByEolPermission = gridOptions.addSubRowByEolPermission ? gridOptions.addSubRowByEolPermission : "*";
			gridOptions.removeRowByEolPermission = gridOptions.removeRowByEolPermission ? gridOptions.removeRowByEolPermission : "*";
			gridOptions.processRowByEolPermission = gridOptions.processRowByEolPermission ? gridOptions.processRowByEolPermission : "*";
		}
	};
	return service;
}

uiGridOperation.$inject = [ 'uiGridOperationService', '$templateCache', 'uiGridConstants' ];
function uiGridOperation(uiGridOperationService, $templateCache, uiGridConstants) {
	return {
		replace : true,
		priority : 0,
		require : '^uiGrid',
		scope : false,
		compile : function() {
			return {
				pre : function($scope, $elm, $attrs, uiGridCtrl) {
					var self = uiGridCtrl.grid;
					uiGridOperationService.initializeGrid(self);
					if (self.options.enableOperation) {
						var operationRowHeaderDef = {
							name : 'operationRowHeaderCol',
							displayName : '',
							width : calculateWidth(),
							minWidth : 10,
							cellTemplate : 'pti/operationRowHeader',
							headerCellTemplate : 'pti/operationHeaderCell',
							enableColumnResizing : false,
							enableColumnMenu : false,
							exporterSuppressExport : true,
							allowCellFocus : true
						};

						self.addRowHeaderColumn(operationRowHeaderDef, -10);
					}

					function calculateWidth() {
						var width = 30, btnSize = 0;
						if (angular.isDefined(self.options.operationRowHeaderWidth)) {
							return self.options.operationRowHeaderWidth;
						}
						if (self.options.enableOperationView) {
							btnSize++;
						}
						if (self.options.enableOperationEdit) {
							btnSize++;
						}
						if (self.options.enableOperationCancel) {
							btnSize++;
						}
						if (self.options.enableOperationDownload) {
							btnSize++;
						}
						if (self.options.enableOperationAddSubRow) {
							btnSize++;
						}
						if (self.options.enableOperationRemove) {
							btnSize++;
						}
						if (self.options.enableOperationProcess) {
							btnSize++;
						}
						if (self.options.enableOperationMoreProcess) {
							btnSize++;
						}
						return width + ((btnSize - 2) >= 0 ? (btnSize - 2) : 0) * 20;
					}
				},
				post : function($scope, $elm, $attrs, uiGridCtrl) {

				}
			};
		}
	};
}

uiGridEolOperation.$inject = [ 'uiGridOperationService', '$templateCache', 'uiGridConstants', 'GridColumn', 'gridUtil' ];
function uiGridEolOperation(uiGridOperationService, $templateCache, uiGridConstants, GridColumn, gridUtil) {
	function eolOperationBuilder(colDef, col, gridOptions) {
		if (colDef.pinnedLeft) {
			col.grid.createRightContainer();
		} else if (colDef.pinnedRight) {
			col.grid.createLeftContainer();
		}
    }
	function addReverseOperationRowHeaderColumn(grid, colDef, order, stopColumnBuild) {
	    var self = grid;

	    // default order
	    if (order === undefined) {
	    	order = 0;
	    }

	    var rowHeaderCol = new GridColumn(colDef, gridUtil.nextUid(), self);
	    rowHeaderCol.isRowHeader = true;
	    if (self.isRTL()) {
	      self.createLeftContainer();
	      rowHeaderCol.renderContainer = 'left';
	    }
	    else {
	      self.createRightContainer();
	      rowHeaderCol.renderContainer = 'right';
	    }

	    // relies on the default column builder being first in array, as it is instantiated as part of grid creation
	    self.columnBuilders[0](colDef,rowHeaderCol,self.options)
	      .then(function(){
	        rowHeaderCol.enableFiltering = false;
	        rowHeaderCol.enableSorting = false;
	        rowHeaderCol.enableHiding = false;
	        rowHeaderCol.headerPriority = order;
	        self.rowHeaderColumns.push(rowHeaderCol);
	        self.rowHeaderColumns = self.rowHeaderColumns.sort(function (a, b) {
	          return a.headerPriority - b.headerPriority;
	        });

	        if (!stopColumnBuild) {
	          self.buildColumns().then(function() {
	              self.preCompileCellTemplates();
	              self.queueGridRefresh();
	            }).catch(angular.noop);
	        }
	      }).catch(angular.noop);
	}
	return {
		replace : true,
		priority : 0,
		require : '^uiGrid',
		scope : false,
		compile : function() {
			return {
				pre : function($scope, $elm, $attrs, uiGridCtrl) {
					var self = uiGridCtrl.grid;
					if (self.options.enableEolOperation) {
						self.registerColumnBuilder(eolOperationBuilder);
						uiGridOperationService.initializeGrid(self);
						var operationRowHeaderDef = {
							name : 'eolOperationRowHeaderCol',
							displayName : 'list.title.action',
							width : calculateWidth(),
							minWidth : 30,
							cellTemplate : 'pti/eolOperationRowHeader',
							headerCellTemplate : "<div role=\"columnheader\" class=\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\"><span class=\"ui-grid-header-cell-label\">{{ col.displayName | translate }}</span></div></div>",
							enableColumnResizing : false,
							enableColumnMenu : false,
							exporterSuppressExport : true,
							allowCellFocus : true
						};
						addReverseOperationRowHeaderColumn(self, operationRowHeaderDef, -10);
					}

					function calculateWidth() {
						var width = 75, btnSize = 0;
						if (angular.isDefined(self.options.operationRowHeaderWidth)) {
							return self.options.operationRowHeaderWidth;
						}
						if (self.options.enableEolOperationView) {
							btnSize++;
						}
						if (self.options.enableEolOperationEdit) {
							btnSize++;
						}
						if (self.options.enableEolOperationCancel) {
							btnSize++;
						}
						if (self.options.enableEolOperationDownload) {
							btnSize++;
						}
						if (self.options.enableEolOperationAddSubRow) {
							btnSize++;
						}
						if (self.options.enableEolOperationRemove) {
							btnSize++;
						}
						if (self.options.enableEolOperationProcess) {
							btnSize++;
						}
						if (self.options.enableEolOperationMoreProcess) {
							btnSize++;
						}
						return width + ((btnSize - 2) >= 0 ? (btnSize - 2) : 0) * 20;
					}
				},
				post : function($scope, $elm, $attrs, uiGridCtrl) {

				}
			};
		}
	};
}

uiGridOperationRowHeaderButtons.$inject = [ '$templateCache', 'uiGridSelectionService', 'gridUtil', '$timeout' ];
function uiGridOperationRowHeaderButtons($templateCache, uiGridSelectionService, gridUtil, $timeout) {
	return {
		replace : true,
		restrict : 'E',
		template : function($elm, $attrs){
			var isEolOprarion = $attrs.eol == undefined ? false : true;
			if (isEolOprarion) {
				return $templateCache.get('pti/eolOperationRowHeaderButtons');
			}
			return $templateCache.get('pti/operationRowHeaderButtons');
		},
		scope : true,
		require : '^uiGrid',
		link : function($scope, $elm, $attrs, uiGridCtrl) {
			var self = uiGridCtrl.grid, watchers = [], watcher, authorization;
			var isEolOprarion = $attrs.eol == undefined ? false : true;
			$scope.$on('$destroy', function() {
				while (watchers.length) {
					(watchers.shift() || angular.noop)();
				}
			});
			$scope.disableElement = function($event) {
				var btn = ($event.srcElement || $event.target).parentElement;
				if (btn.disabled) {
					return false;
				}
				btn.disabled = true;
				$timeout(function() {
					btn.disabled = false;
				}, 1000);
			};
			authorization = self.appScope ? (self.appScope.authorization || ((self.appScope.$stateParams) ? self.appScope.$stateParams.authorization : null)) : null;
			initFilterRowOperationCallBack();
			initViewButtonClickCallBack();
			initEditButtonClickCallBack();
			initCancelButtonClickCallBack();
			initDownloadButtonClickCallBack();
			initAddSubRowButtonClickCallBack();
			initRemoveButtonClickCallBack();
			initProcessButtonClickCallBack();
			function initFilterRowOperationCallBack() {
				if (self.options.filterRowOperation) {
					if (angular.isString(self.options.filterRowOperation)) {
						watcher = self.appScope.$watch(self.options.filterRowOperation, function(filterRowOperation) {
							$scope.filterRowOperation = function(row, operation) {
								if (angular.isFunction(filterRowOperation)) {
									return filterRowOperation(row, operation);
								} else {
									return false;
								}
							}
						});
						watchers.push(watcher);
					} else if (angular.isFunction(self.options.filterRowOperation)) {
						$scope.filterRowOperation = function (row, operation) {
							return self.options.filterRowOperation(row, operation);
						}
					} else {
						return false;
					}
				} else {
					$scope.filterRowOperation = function(row, operation) {
						return false;
					}
				}
			}

			function initViewButtonClickCallBack() {
				var viewPermission = isEolOprarion ? self.options.viewRowByEolPermission : self.options.viewRowPermission;
				$scope.viewPermission = {
					permission : viewPermission,
					authorization : authorization
				}
				var callback = isEolOprarion ? self.options.viewRowByEol : self.options.viewRow;
				if (callback && angular.isString(callback)) {
					$scope.viewButtonClick = angular.noop;
					watcher = self.appScope.$watch(callback, function(view) {
						$scope.viewButtonClick = function(row, $event) {
							(view || angular.noop)(row);
						};
					});
					watchers.push(watcher);
				} else if (angular.isFunction(callback)) {
					$scope.viewButtonClick = function(row, $event) {
						callback(row);
					};
				} else {
					$scope.viewButtonClick = angular.noop;
				}
			}

			function initEditButtonClickCallBack() {
				var editPermission = isEolOprarion ? self.options.editRowByEolPermission : self.options.editRowPermission;
				$scope.editPermission = {
					permission : editPermission,
					authorization : authorization
				}
				var callback = isEolOprarion ? self.options.editRowByEol : self.options.editRow;
				if (callback && angular.isString(callback)) {
					$scope.editButtonClick = angular.noop;
					watcher = self.appScope.$watch(callback, function(edit) {
						$scope.editButtonClick = function(row, $event) {
							(edit || angular.noop)(row);
						};
					});
					watchers.push(watcher);
				} else if (angular.isFunction(callback)) {
					$scope.editButtonClick = function(row, $event) {
						callback(row);
					};
				} else {
					$scope.editButtonClick = angular.noop;
				}
			}
			
			function initCancelButtonClickCallBack() {
				var cancelPermission = isEolOprarion ? self.options.cancelRowByEolPermission : self.options.cancelRowPermission;
				$scope.cancelPermission = {
					permission : cancelPermission,
					authorization : authorization
				}
				var callback = isEolOprarion ? self.options.cancelRowByEol : self.options.cancelRow;
				if (callback && angular.isString(callback)) {
					$scope.cancelButtonClick = angular.noop;
					watcher = self.appScope.$watch(callback, function(cancel) {
						$scope.cancelButtonClick = function(row, $event) {
							(cancel || angular.noop)(row);
						};
					});
					watchers.push(watcher);
				} else if (angular.isFunction(callback)) {
					$scope.cancelButtonClick = function(row, $event) {
						callback(row);
					};
				} else {
					$scope.cancelButtonClick = angular.noop;
				}
			}
			
			function initDownloadButtonClickCallBack() {
				var downloadPermission = isEolOprarion ? self.options.downloadRowByEolPermission : self.options.downloadRowPermission;
				$scope.downloadPermission = {
					permission : downloadPermission,
					authorization : authorization
				}
				var callback = isEolOprarion ? self.options.downloadRowByEol : self.options.downloadRow;
				if (callback && angular.isString(callback)) {
					$scope.downloadButtonClick = angular.noop;
					watcher = self.appScope.$watch(callback, function(download) {
						$scope.downloadButtonClick = function(row, $event) {
							(download || angular.noop)(row);
						};
					});
					watchers.push(watcher);
				} else if (angular.isFunction(callback)) {
					$scope.downloadButtonClick = function(row, $event) {
						callback(row);
					};
				} else {
					$scope.downloadButtonClick = angular.noop;
				}
			}
			
			function initAddSubRowButtonClickCallBack() {
				var addSubPermission = isEolOprarion ? self.options.addSubRowByEolPermission : self.options.addSubRowPermission;
				$scope.addSubPermission = {
					permission : addSubPermission,
					authorization : authorization
				}
				var callback = isEolOprarion ? self.options.addSubRowByEol : self.options.addSubRow;
				if (callback && angular.isString(callback)) {
					$scope.addSubRowButtonClick = angular.noop;
					watcher = self.appScope.$watch(callback, function(addSubRow) {
						$scope.addSubRowButtonClick = function(row, $event) {
							(addSubRow || angular.noop)(row);
						};
					});
					watchers.push(watcher);
				} else if (angular.isFunction(callback)) {
					$scope.addSubRowButtonClick = function(row, $event) {
						callback(row);
					};
				} else {
					$scope.addSubRowButtonClick = angular.noop;
				}
			}

			function initRemoveButtonClickCallBack() {
				var removePermission = isEolOprarion ? self.options.removeRowByEolPermission : self.options.removeRowPermission;
				$scope.removePermission = {
					permission : removePermission,
					authorization : authorization
				}
				var callback = isEolOprarion ? self.options.removeRowByEol : self.options.removeRow;
				if (callback && angular.isString(callback)) {
					$scope.removeButtonClick = angular.noop;
					watcher = self.appScope.$watch(callback, function(remove) {
						$scope.removeButtonClick = function(row, $event) {
							var promise = (remove || angular.noop)(row);
							if (promise && angular.isFunction(promise.then)) {
								promise.then(function() {
									removeRow(row, $event);
								});
							} else {
								removeRow(row, $event);
							}
							self.appScope.$emit('REMOVE_ROWS', [row]);
						};
					});
					watchers.push(watcher);
				} else if (angular.isFunction(callback)) {
					$scope.removeButtonClick = function(row, $event) {
						var promise = callback(row);
						if (promise && angular.isFunction(promise.then)) {
							promise.then(function() {
								removeRow(row, $event);
							});
						} else {
							removeRow(row, $event);
						}
						self.appScope.$emit('REMOVE_ROWS', [row]);
					};
				} else {
					$scope.removeButtonClick = function(row, $event) {
						removeRow(row, $event);
						self.appScope.$emit('REMOVE_ROWS', [row]);
					}
				}
			}
			
			function initProcessButtonClickCallBack() {
				var processPermission = isEolOprarion ? self.options.processRowByEolPermission : self.options.processRowPermission;
				$scope.processPermission = {
					permission : processPermission,
					authorization : authorization
				}
				var callback = isEolOprarion ? self.options.processRowByEol : self.options.processRow;
				if (callback && angular.isString(callback)) {
					$scope.processButtonClick = angular.noop;
					watcher = self.appScope.$watch(callback, function(process) {
						$scope.processButtonClick = function(row, $event) {
							(process || angular.noop)(row);
							self.appScope.$emit('REMOVE_ROWS', [row]);
						};
					});
					watchers.push(watcher);
				} else if (angular.isFunction(callback)) {
					$scope.processButtonClick = function(row, $event) {
						callback(row);
						self.appScope.$emit('REMOVE_ROWS', [row]);
					};
				} else {
					$scope.processButtonClick = function(row, $event) {
						self.appScope.$emit('REMOVE_ROWS', [row]);
					}
				}
			}
			$scope.moreProcessPermission = function(processConfig) {
				$scope.permission = {
					permission :  processConfig.permission,
					authorization : authorization
				};
			};
			$scope.moreProcessClick = function(row, processConfig, $event) {
				var callback = processConfig.callback;
				if (callback && angular.isString(callback)) {
					callback = self.appScope.$eval(callback);
				}
				if (angular.isFunction(callback)) {
					callback(row);
				}
			};
			function removeRow(row, $event) {
				var selectedRows;
				if (row !== null && row.isSelected) {
					uiGridSelectionService.toggleRowSelection(self, row, $event, self.options.multiSelect, self.options.noUnselect);
				}
				removeItem(self.options.data, row.entity);
				selectedRows = getSelectedRows();
				if (selectedRows && selectedRows.length > 0 && selectedRows[0].isSelected) {
					uiGridSelectionService.toggleRowSelection(self, selectedRows[0], $event, self.options.multiSelect, self.options.noUnselect);
					$timeout(function() {
						uiGridSelectionService.toggleRowSelection(self, selectedRows[0], $event, self.options.multiSelect, self.options.noUnselect);
					});
				}
			}

			function getSelectedRows() {
				return self.rows.filter(function(row) {
					return row.isSelected;
				});
			}

			function removeItem(data, item) {
				var scope, items;
				if (angular.isString(self.options.data)) {
					if (self.options.data.match(/ngModel\..*/)) {
						scope = getNgModelScope($scope) ;
					} else {
						scope = self.appScope;
					}
					items = scope.$eval(self.options.data);
				} else {
					items = data;
				}
				angular.forEach(items, function(row, index) {
					if (self.options.rowEquality(row, item) || (row.primaryKey == item.primaryKey && item.primaryKey != undefined)) {
						if (!(row && row.dataStatus) || 'C' == row.dataStatus) {
							items.splice(index, 1);
						} else {
							items[index].dataStatus = 'D';
						}
					}
				});
			}
			
			function getNgModelScope(scope) {
				if (!scope) {
					return null;
				}
				if (scope.hasOwnProperty('ngModel')) {
					return scope;
				} else {
					return getNgModelScope(scope.$parent);
				}
			}
		}
	};
}

uiGridOperationHeaderButtons.$inject = [ '$templateCache', '$timeout', 'uiGridGroupingService', 'uiGridSelectionService', 'modalService' ];
function uiGridOperationHeaderButtons($templateCache, $timeout, uiGridGroupingService, uiGridSelectionService, modalService) {
	return {
		replace : true,
		restrict : 'E',
		template : $templateCache.get('pti/operationHeaderButtons'),
		scope : true,
		link : function($scope, $elm, $attrs, uiGridCtrl) {
			var self = $scope.col.grid;
			var watchers = [], watcher;
			$scope.$on('$destroy', function() {
				while (watchers.length) {
					(watchers.shift() || angular.noop)();
				}
			});
			if (self.options.addRow && angular.isString(self.options.addRow)) {
				$scope.addButtonClick = angular.noop;
				watcher = self.appScope.$watch(self.options.addRow, function(add) {
					$scope.addButtonClick = function($event) {
						$scope.disableElement($event);
						var promise, row = { dataStatus : 'C' };
						if (!angular.isFunction(add)) {
							_addRow(self.options.data, row);
							return;
						}
						promise = (add || angular.noop)(row);
						if (promise && angular.isFunction(promise.then)) {
							promise.then(function() {
								_addRow(self.options.data, row);
							});
						} else {
							_addRow(self.options.data, row);
						}
						self.appScope.$emit('ADD_ROW', row);
					};
					self.options.__addRow = $scope.addButtonClick;
				});
				watchers.push(watcher);
			} else if (angular.isFunction(self.options.addRow)) {
				$scope.addButtonClick = function($event) {
					$scope.disableElement($event);
					var row = { dataStatus : 'C' };
					var promise = self.options.addRow(row);
					if (promise && angular.isFunction(promise.then)) {
						promise.then(function() {
							_addRow(self.options.data, row);
						});
					} else {
						_addRow(self.options.data, row);
					}
					self.appScope.$emit('ADD_ROW', row);
				};
				self.options.__addRow = $scope.addButtonClick;
			} else {
				$scope.addButtonClick = function($event) {
					$scope.disableElement($event);
					var row = { dataStatus : 'C' };
					_addRow(self.options.data, row);
					self.appScope.$emit('ADD_ROW', row);
				};
				self.options.__addRow = $scope.addButtonClick;
			}
			
			if (self.options.removeAllRows && angular.isString(self.options.removeAllRows)) {
				$scope.removeAllButtonClick = angular.noop;
				watcher = self.appScope.$watch(self.options.removeAllRows, function(removeAll) {
					$scope.removeAllButtonClick = function($event) {
						var promise;
						if (!angular.isFunction(removeAll)) {
							removeAllRows($event);
							return;
						}
						promise = (removeAll || angular.noop)();
						if (promise && angular.isFunction(promise.then)) {
							promise.then(function() {
								removeAllRows($event);
							});
						} else {
							removeAllRows($event);
						}
						self.appScope.$emit('REMOVE_ROWS', getAllRows());
					};
				});
				watchers.push(watcher);
			} else if (angular.isFunction(self.options.removeAllRows)) {
				$scope.removeAllButtonClick = function($event) {
					var promise;
					promise = self.options.removeAllRows();
					if (promise && angular.isFunction(promise.then)) {
						promise.then(function() {
							removeAllRows($event);
						});
					} else {
						removeAllRows($event);
					}
					self.appScope.$emit('REMOVE_ROWS', getAllRows());
				};
			} else {
				$scope.removeAllButtonClick = function($event) {
					removeAllRows($event);
					self.appScope.$emit('REMOVE_ROWS', getAllRows());
				}
			}

			if (self.options.removeSelectedRows && angular.isString(self.options.removeSelectedRows)) {
				$scope.removeSelectedButtonClick = angular.noop;
				watcher = self.appScope.$watch(self.options.removeSelectedRows, function(removeSelected) {
					$scope.removeSelectedButtonClick = function($event) {
						var promise, selectedRows = getSelectedRows();
						if (!selectedRows || selectedRows.length == 0) {
							modalService.openErrorDialogs({
								messages : [ 'title.dialogs.info.norecsel' ]
							});
							return false;
						}
						if (!angular.isFunction(removeSelected)) {
							removeSelectedRows($event);
							return;
						}
						promise = (removeSelected || angular.noop)();
						if (promise && angular.isFunction(promise.then)) {
							promise.then(function() {
								removeSelectedRows($event);
							});
						} else {
							removeSelectedRows($event);
						}
						self.appScope.$emit('REMOVE_ROWS', selectedRows);
					};
				});
				watchers.push(watcher);
			} else if (angular.isFunction(self.options.removeSelectedRows)) {
				$scope.removeSelectedButtonClick = function($event) {
					var promise, selectedRows = getSelectedRows();
					if (!selectedRows || selectedRows.length == 0) {
						modalService.openErrorDialogs({
							messages : [ 'title.dialogs.info.norecsel' ]
						});
						return false;
					}
					promise = self.options.removeSelectedRows();
					if (promise && angular.isFunction(promise.then)) {
						promise.then(function() {
							removeSelectedRows($event);
						});
					} else {
						removeSelectedRows($event);
					}
					self.appScope.$emit('REMOVE_ROWS', selectedRows);
				};
			} else {
				$scope.removeSelectedButtonClick = function($event) {
					var selectedRows = getSelectedRows();
					if (!selectedRows || selectedRows.length == 0) {
						modalService.openErrorDialogs({
							messages : [ 'title.dialogs.info.norecsel' ]
						});
						return false;
					}
					removeSelectedRows($event);
					self.appScope.$emit('REMOVE_ROWS', selectedRows);
				}
			}
			
			$scope.disableElement = function ($event) {
				var btn = ($event.srcElement || $event.target).parentElement;
				if (btn.disabled) {
					return false;
				}
				btn.disabled = true;
				$timeout(function() {
					btn.disabled = false;
				}, 1000);
			};
			
			function removeAllRows($event) {
				var rows = getAllRows();
				angular.forEach(rows, function(row) {
					if (row !== null && row.isSelected) {
						uiGridSelectionService.toggleRowSelection(self, row, $event, self.options.multiSelect, self.options.noUnselect);
					}
				});
				angular.forEach(rows, function(row) {
					removeItem(self.options.data, row.entity);
				});
				return rows;
			}
			
			function removeSelectedRows($event) {
				var selectedRows = getSelectedRows();
				angular.forEach(selectedRows, function(row) {
					if (row !== null && row.isSelected) {
						uiGridSelectionService.toggleRowSelection(self, row, $event, self.options.multiSelect, self.options.noUnselect);
					}
				});
				angular.forEach(selectedRows, function(selectedRow) {
					removeItem(self.options.data, selectedRow.entity);
				});
				return selectedRows;
			}
			
			function _addRow(data, row) {
				var scope;
				if (angular.isString(self.options.data)) {
					if (self.options.data.match(/ngModel\..*/)) {
						scope = getNgModelScope($scope);
					} else {
						scope = self.appScope;
					}
					data = scope.$eval(self.options.data);
				}
				data.push(row);
				sort(data, self);
				return row;
			}
			
			function sort(data, grid) {
				var columnSettings = uiGridGroupingService.getGrouping(grid);
				columnSettings.grouping.reverse();
				columnSettings.grouping.forEach(function(groupItem, index) {
					data.sort(function(a, b) {
						if (a[groupItem.field] != null && a[groupItem.field] != undefined) {
							return a[groupItem.field].localeCompare(b[groupItem.field]);
						} else if (b[groupItem.field] != null && b[groupItem.field] != undefined) {
							return -1;
						} else {
							return 0;
						}
					});
				});
			}
			
			function getSelectedRows() {
				if (self._selectedRows) {
					return self._selectedRows;
				} else {
					return self.rows.filter(function(row) {
						return row.isSelected;
					});
				}
			}
			
			function getAllRows() {
				return self.rows;			
			}
			
			function removeItem(data, item) {
				var scope, items;
				if (angular.isString(self.options.data)) {
					if (self.options.data.match(/ngModel\..*/)) {
						scope = getNgModelScope($scope);
					} else {
						scope = self.appScope;
					}
					items = scope.$eval(self.options.data);
				} else {
					items = data;
				}
				angular.forEach(items, function(row, index) {
					if (self.options.rowEquality(row, item) || (row.primaryKey == item.primaryKey && item.primaryKey != undefined)) {
						if(!(row && row.dataStatus) || 'C' == row.dataStatus) {
							items.splice(index, 1);
						} else {
							items[index].dataStatus = 'D';
						}
					}
				});
			}
			function getNgModelScope(scope) {
				if (!scope) {
					return null;
				}
				if (scope.hasOwnProperty('ngModel')) {
					return scope;
				} else {
					return getNgModelScope(scope.$parent);
				}
			}
		}
	};
}

uiGridOperationTemplates.$inject = [ '$templateCache', 'rowSorter' ];
function uiGridOperationTemplates($templateCache, rowSorter) {
	'use strict';
	if (!rowSorter.guessSortFnOveride) {
		rowSorter.guessSortFn = function guessSortFn(itemType) {
			switch (itemType) {
			case "number":
				return rowSorter.sortNumber;
			case "numberStr":
				return rowSorter.sortNumberStr;
			case "boolean":
				return rowSorter.sortBool;
			case "string":
				return rowSorter.sortAlpha;
			case "date":
				return rowSorter.sortDate;
			case "object":
				return rowSorter.basicSort;
			default:
				return rowSorter.sortAlpha;
			}
		};
		rowSorter.guessSortFnOveride = true;
	}
	$templateCache.put('fs/layout/template/uiGrid/tooltipTpl.html', ''
		+ '<ul class="fstooltip list-inline">\n' 
		+ '   <li ng-repeat="message in (row.compareResult.fields[col.colDef.model].tooltip || col.colDef.tooltip)">{{message | translate }}</li>\n'
		+ '</ul>\n'
	);
	
	$templateCache.put('fs-grid/uiGridCell/tooltip', '' 
		+ '<ul class="list-inline"><li ng-repeat="message in tooltipMessage">{{ message | translate }}</ul>\n'
	);
	
	
	$templateCache.put('pti/operationRowHeader', '' 
		+ '<div class="ui-grid-disable-operation">' 
		+ '    <div class="ui-grid-cell-contents operationRowHeader">'
		+ '        <ui-grid-operation-row-header-buttons></ui-grid-operation-row-header-buttons>' 
		+ '    </div>' 
		+ '</div>');
	
	$templateCache.put('pti/operationRowHeaderButtons', '' 
		+ '<div class="operationRowHeaderButtons">'
		+ '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationView && !(filterRowOperation(row, \'view\') == true)" ng-click="viewRowTooltipIsOpen=false;disableElement($event);viewButtonClick(row, $event)"'
		+ '         tooltip-is-open="viewRowTooltipIsOpen" uib-tooltip="{{\'label.global.view\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
		+ '    	   <span class="icon icon-view"></span>'
		+ '    </button>'
		+ '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationEdit && !(filterRowOperation(row, \'edit\') == true)" ng-click="editRowTooltipIsOpen=false;disableElement($event);editButtonClick(row, $event)"'
		+ '         tooltip-is-open="editRowTooltipIsOpen" uib-tooltip="{{\'label.global.edit\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
		+ '    	   <span class="icon icon-edit"></span>'
		+ '    </button>'
		+ '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationAddSubRow && !(filterRowOperation(row, \'add\') == true)" ng-click="addSubRowTooltipIsOpen=false;disableElement($event);addSubRowButtonClick(row, $event)"'
		+ '        tooltip-is-open="addSubRowTooltipIsOpen" uib-tooltip="{{\'label.global.addsubrow\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
		+ '    	   <span class="icon icon-add_1"></span>'
		+ '    </button>'
		+ '    <button type="button" class="btn btn-default btn-xs" ng-show="!grid.options.enableRowHeaderSelection && grid.options.enableOperationRemove && !(filterRowOperation(row, \'remove\') == true)" ng-click="removeRowTooltipIsOpen=false;disableElement($event);removeButtonClick(row, $event)"'
		+ '        tooltip-is-open="removeRowTooltipIsOpen" uib-tooltip="{{\'label.global.remove\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
		+ '    	   <span class="icon icon-remove"></span>'
		+ '    </button>'
		+ '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationProcess && !(filterRowOperation(row, \'process\') == true)" ng-click="processRowTooltipIsOpen=false;disableElement($event);processButtonClick(row, $event)"'
		+ '        tooltip-is-open="processRowTooltipIsOpen" uib-tooltip="{{\'label.global.process\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
		+ '    	   <span class="icon icon-play"></span>'
		+ '    </button>'
		+ '    <div uib-dropdown dropdown-append-to-body="\'true\'" ng-show="grid.options.enableOperationMoreProcess && !(filterRowOperation(row, \'more\') == true)" style="display:inline-block">'
		+ '      <button uib-dropdown-toggle type="button" class="btn btn-default btn-xs" ng-click="moreProcessRowTooltipIsOpen=false;disableElement($event);moreProcessButtonClick(row, $event)"'
		+ '        tooltip-is-open="moreProcessRowTooltipIsOpen" uib-tooltip="{{grid.options.moreProcess.tooltip || \'label.global.processmore\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
		+ '    	   <span class="icon icon-{{grid.options.moreProcess.icon || \'more\'}}"></span>'
		+ '      </button>'
		+ '      <ul class="animated fadeInUp dropdown-menu-right" uib-dropdown-menu>'
		+ '        <li ng-repeat="processConfig in grid.options.moreProcess.items" fs-permission="permission" ng-init="moreProcessPermission(processConfig)" ng-show="!(filterRowOperation(row, processConfig.name) == true)"><a href="#" ng-click="moreProcessClick(row, $event)"><i class="icon icon-{{processConfig.icon}}"></i><span>{{processConfig.label|translate}}</span></a></li>'
		+ '      </ul>'
		+ '    <div>'
		+ '</div>');
	
	$templateCache.put('pti/eolOperationRowHeader', '' 
			+ '<div class="ui-grid-disable-operation">' 
			+ '    <div class="ui-grid-cell-contents operationRowHeader">'
			+ '        <ui-grid-operation-row-header-buttons eol></ui-grid-operation-row-header-buttons>' 
			+ '    </div>' 
			+ '</div>');
	
	$templateCache.put('pti/eolOperationRowHeaderButtons', '' 
			+ '<div class="operationRowHeaderButtons">'
			+ '    <button type="button" fs-permission="viewPermission" class="btn btn-default btn-xs" ng-show="grid.options.enableEolOperationView && !(filterRowOperation(row, \'view\') == true)" ng-click="viewRowTooltipIsOpen=false;disableElement($event);viewButtonClick(row, $event)"'
			+ '         tooltip-is-open="viewRowTooltipIsOpen" uib-tooltip="{{grid.options.viewRowByEol.tooltip || (\'label.global.view\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
			+ '    	   <span class="icon icon-{{grid.options.viewRowByEol.icon || \'view\'}}"></span>'
			+ '    </button>'
			+ '    <button type="button" fs-permission="editPermission" class="btn btn-default btn-xs" ng-show="grid.options.enableEolOperationEdit && !(filterRowOperation(row, \'edit\') == true)" ng-click="editRowTooltipIsOpen=false;disableElement($event);editButtonClick(row, $event)"'
			+ '         tooltip-is-open="editRowTooltipIsOpen" uib-tooltip="{{grid.options.editRowByEol.tooltip || (\'label.global.edit\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
			+ '    	   <span class="icon icon-{{grid.options.editRowByEol.icon || \'edit\'}}"></span>'
			+ '    </button>'
			+ '    <button type="button" fs-permission="cancelPermission" class="btn btn-default btn-xs" ng-show="grid.options.enableEolOperationCancel && !(filterRowOperation(row, \'cancel\') == true)" ng-click="cancelRowTooltipIsOpen=false;disableElement($event);cancelButtonClick(row, $event)"'
			+ '         tooltip-is-open="cancelRowTooltipIsOpen" uib-tooltip="{{grid.options.cancelRowByEol.tooltip || (\'label.global.cancel\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
			+ '    	   <span class="icon icon-{{grid.options.cancelRowByEol.icon || \'cancel\'}}"></span>'
			+ '    </button>'
			+ '    <button type="button" fs-permission="downloadPermission" class="btn btn-default btn-xs" ng-show="grid.options.enableEolOperationDownload && !(filterRowOperation(row, \'download\') == true)" ng-click="downloadRowTooltipIsOpen=false;disableElement($event);downloadButtonClick(row, $event)"'
			+ '         tooltip-is-open="downloadRowTooltipIsOpen" uib-tooltip="{{grid.options.downloadRowByEol.tooltip || (\'label.global.download\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
			+ '    	   <span class="icon icon-{{grid.options.downloadRowByEol.icon || \'download\'}}"></span>'
			+ '    </button>'
			+ '    <button type="button" fs-permission="addSubPermission" class="btn btn-default btn-xs" ng-show="grid.options.enableEolOperationAddSubRow && !(filterRowOperation(row, \'add\') == true)" ng-click="addSubRowTooltipIsOpen=false;disableElement($event);addSubRowButtonClick(row, $event)"'
			+ '        tooltip-is-open="addSubRowTooltipIsOpen" uib-tooltip="{{grid.options.addSubRowByEol.tooltip || (\'label.global.addsubrow\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
			+ '    	   <span class="icon icon-{{grid.options.addSubRowByEol.icon || \'add_1\'}}"></span>'
			+ '    </button>'
			+ '    <button type="button" fs-permission="removePermission" class="btn btn-default btn-xs" ng-show="!grid.options.enableRowHeaderSelection && grid.options.enableEolOperationRemove && !(filterRowOperation(row, \'remove\') == true)" ng-click="removeRowTooltipIsOpen=false;disableElement($event);removeButtonClick(row, $event)"'
			+ '        tooltip-is-open="removeRowTooltipIsOpen" uib-tooltip="{{grid.options.removeRowByEol.tooltip || (\'label.global.remove\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
			+ '    	   <span class="icon icon-{{grid.options.removeRowByEol.icon || \'remove\'}}"></span>'
			+ '    </button>'
			+ '    <button type="button" fs-permission="processPermission" class="btn btn-default btn-xs" ng-show="grid.options.enableEolOperationProcess && !(filterRowOperation(row, \'process\') == true)" ng-click="processRowTooltipIsOpen=false;disableElement($event);processButtonClick(row, $event)"'
			+ '        tooltip-is-open="processRowTooltipIsOpen" uib-tooltip="{{grid.options.processRowByEol.tooltip || (\'label.global.process\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
			+ '    	   <span class="icon icon-{{grid.options.processRowByEol.icon || \'play\'}}"></span>'
			+ '    </button>'
			+ '    <div uib-dropdown dropdown-append-to-body="\'true\'" ng-show="grid.options.enableEolOperationMoreProcess && !(filterRowOperation(row, \'more\') == true)" style="display:inline-block">'
			+ '      <button uib-dropdown-toggle type="button" class="btn btn-default btn-xs" ng-click="moreProcessRowTooltipIsOpen=false;disableElement($event);moreProcessButtonClick(row, $event)"'
			+ '        tooltip-is-open="moreProcessRowTooltipIsOpen" uib-tooltip="{{grid.options.moreProcessByEol.tooltip || \'label.global.processmore\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
			+ '    	   <span class="icon icon-{{grid.options.moreProcessByEol.icon || \'more\'}}"></span>'
			+ '      </button>'
			+ '      <ul class="animated fadeInUp dropdown-menu-right" uib-dropdown-menu>'
			+ '        <li ng-repeat="processConfig in grid.options.moreProcessByEol.items" fs-permission="moreProcessPermission(processConfig)" ng-show="!(filterRowOperation(row, processConfig.name) == true)"><a href="#" ng-click="moreProcessClick(row, processConfig, $event)"><i class="icon icon-{{processConfig.icon}}"></i><span>{{processConfig.label|translate}}</span></a></li>'
			+ '      </ul>'
			+ '    <div>'
			+ '</div>');
	
	$templateCache.put('pti/operationHeaderCell', '' 
		+ '<div class="operationHeaderCell">' 
		+ '    <div class="ui-grid-cell-contents operationHeaderCell" col-index="renderIndex">'
		+ '        <ui-grid-operation-header-buttons></ui-grid-operation-add-button>'
		+ '    </div>'
		+ '</div>');
	
	$templateCache.put('pti/operationHeaderButtons', '' 
		+ '<div class="operationHeaderButtons">'
//		+ '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationAdd" ng-click="addTooltipIsOpen=false;disableElement($event);addButtonClick($event)"'
//		+ '        tooltip-is-open="addTooltipIsOpen" uib-tooltip="{{\'label.global.add\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
//		+ '    	   <span class="icon icon-add_1"></span>'
//		+ '    </button>'
		+ '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationRemoveAll" ng-click="removeAllTooltipIsOpen=false;disableElement($event);removeAllButtonClick($event)"'
		+ '        tooltip-is-open="removeAllTooltipIsOpen" uib-tooltip="{{\'label.global.removeselected\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
		+ '    	   <span class="icon icon-remove"></span>'
		+ '    </button>'
		+ '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableRowHeaderSelection && grid.options.enableOperationRemoveSelected" ng-click="removeTooltipIsOpen=false;disableElement($event);removeSelectedButtonClick($event)"'
		+ '        tooltip-is-open="removeTooltipIsOpen" uib-tooltip="{{\'label.global.removeselected\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
		+ '    	   <span class="icon icon-remove"></span>'
		+ '    </button>'
		+ '</div>');
		
	$templateCache.put('ui-grid/ui-grid-grid-footer',
		"<div class=\"ui-grid-footer-info ui-grid-grid-footer\"><span>{{\"label.pagination.totalitems\"|translate}}: {{grid.options.totalItems}}</span> <span ng-if=\"grid.renderContainers.body.visibleRowCache.length !== grid.rows.length\" class=\"ngLabel\">({{\"search.showingItems\" | t}} {{grid.renderContainers.body.visibleRowCache.length}})</span></div>"
	);
	
	$templateCache.put('ui-grid/gridFooterSelectedItems',
		"<span ng-if=\"grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected\">({{\"label.pagination.selecteditems\"|translate}}: {{grid.selection.selectedCount}})</span>"
	);
	
	$templateCache.put('ui-grid/pagination', ''
		+ '<div role="contentinfo" class="ui-grid-pager-panel paginationBar clearfix" ui-grid-pager ng-if="grid.options.enablePaginationControls">'
		+ '    <ul class="pull-right" uib-pagination template-url="ui-grid/pagination/pagination.html" items-per-page="grid.options.paginationPageSize" total-items="grid.options.totalItems" ng-model="grid.options.paginationCurrentPage" boundary-links="true" first-text="<<" previous-text="<" next-text=">" last-text=">>"></ul>'
		+ '    <div class="pagination ui-grid-pager-row-count-picker pull-right" ng-if="grid.options.paginationPageSizes.length > 1 && !grid.options.useCustomPagination">'
		+ '       <label> {{"label.pagination.go"|translate}} </label> <input type="number" class="form-control input-sm btn-xs" ui-grid-one-bind-title="aria.pageSelected" ui-grid-one-bind-aria-label="aria.pageSelected" class="ui-grid-pager-control-input" ng-model="grid.options.paginationCurrentPage" ng-keydown="grid.options.pageNoKeydown()" ng-model-options="{ updateOn: \'blur\' }" style="width:60px" min="1" max="{{ paginationApi.getTotalPages() }}" required>'
		+ '       <span class="ui-grid-pager-max-pages-number" ng-show="paginationApi.getTotalPages() > 0">/ {{ paginationApi.getTotalPages() }}</span>'
		+ '    </div>'
		+ '    <div class="pagination ui-grid-pager-row-count-picker pull-right" ng-if="grid.options.paginationPageSizes.length > 1 && !grid.options.useCustomPagination">'
		+ '       <label style="padding-right:8px;">{{grid.options.totalItems}} {{\"label.pagination.totalitems\"|translate}} </label>  <label> {{"label.pagination.pagesize"|translate}} </label> <select class="form-control input-sm btn-xs" ui-grid-one-bind-aria-labelledby-grid="\'items-per-page-label\'" ng-model="grid.options.paginationPageSize" ng-options="o as o for o in grid.options.paginationPageSizes"></select>'
		+ '    </div>'
		+ '</div>'
	);
	
	$templateCache.put('ui-grid/pagination/pagination.html', ''
		+ '<li ng-if="::boundaryLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-first"><a href ng-click="selectPage(1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle><span class="icon icon-firstpage"></span></a></li>\n'
		+ '<li ng-if="::directionLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-prev"><a href ng-click="selectPage(page - 1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle><span class="icon icon-page-left"></span></a></li>\n'
		+ '<li ng-if="page > 6" class="pagination-page disabled"><a href uib-tabindex-toggle>...</a></li>\n'
		+ '<li ng-repeat="pageItem in pages track by $index" ng-class="{active: pageItem.active,disabled: ngDisabled&&!pageItem.active}" class="pagination-page">'
		+ '  <a href ng-click="selectPage(pageItem.number, $event)" ng-if="(pageItem.number <= page + 5) && (pageItem.number >= page - 5)" ng-disabled="ngDisabled&&!pageItem.active" uib-tabindex-toggle>{{pageItem.text}}</a>'
		+ '</li>\n'
		+ '<li ng-if="page < pages.length - 5" class="pagination-page disabled"><a href uib-tabindex-toggle>...</a></li>\n'
		+ '<li ng-if="::directionLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-next"><a href ng-click="selectPage(page + 1, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle><span class="icon icon-page-right"></span></a></li>\n'
		+ '<li ng-if="::boundaryLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-last"><a href ng-click="selectPage(totalPages, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle><span class="icon icon-lastpage"></span></a></li>\n'
	);
	
	$templateCache.put('ui-grid/selectionRowHeaderButtons', ''
		+ '<div class="selectionRowHeaderButtons">'
		+ '    <input class="rowHeader" type="{{grid.options.multiSelect ? \'checkbox\' : \'radio\'}}" id="{{grid.id}}" ng-if="!row.groupHeader" ng-disabled="!grid.options.isRowSelectable(row)" ng-checked="row.isSelected" ng-click="selectButtonClick(row, $event)"><label ng-if="!row.groupHeader" for="{{row.uid}}" >&nbsp;</label>'
		+ '</div>'
	);
	
	$templateCache.put('ui-grid/selectionSelectAllButtons', ''
		+ '<div class="selectionSelectAllButtons">'
		+ '    <input type="checkbox" id="{{grid.id}}" ng-show="grid.options.multiSelect" ng-checked="grid.selection.selectAll" ng-click="headerButtonClick($event)"><label ng-show="grid.options.multiSelect"  for="{{grid.id}}">&nbsp;</label>'
		+ '</div>'
	);
	
	$templateCache.put('ui-grid/ui-grid-header', "" 
			+ "<div role=\"rowgroup\" class=\"ui-grid-header\">\n" 
			+ " <!-- theader -->\n" 
			+ " <div class=\"ui-grid-top-panel\">\n" 
			+ "   <div class=\"ui-grid-header-viewport\">\n" 
			+ "     <div class=\"ui-grid-header-canvas\">\n" 
			+ "       <div class=\"ui-grid-header-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\">\n" 
			+ "         <div role=\"row\" class=\"ui-grid-header-cell-row\">\n" 
			+ "           <div class=\"ui-grid-header-cell ui-grid-clearfix\" ng-mouseover=\"col.colDef._hover=true\" ng-mouseleave=\"col.colDef._hover=false\" ng-class=\"{'hover': col.colDef._hover}\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" ui-grid-header-cell col=\"col\" render-index=\"$index\"></div>\n" 
			+ "           </div>\n" 
			+ "         </div>\n" 
			+ "       </div>\n" 
			+ "   </div>\n" 
			+ " </div>\n" 
			+ "</div>" );
	
	$templateCache.put('ui-grid/uiGridHeaderCell', ""
		+ "<div role=\"columnheader\" ng-class=\"{ 'sortable': sortable, 'ui-grid-header-cell-last-col': isLastCol }\" aria-sort=\"{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending' : (!col.sort.direction ? 'none' : 'other'))}}\">\n"
		+ "    <div role=\"button\" tabindex=\"0\" ng-keydown=\"handleKeyDown($event)\" ng-mouseover=\"col.colDef._hover=true\" ng-mouseleave=\"col.colDef._hover=false\" ng-class=\"{'text-right':col.colDef.textAlign == 'right', 'text-left':col.colDef.textAlign == 'left', 'text-center':col.colDef.textAlign == 'center', 'hover': col.colDef._hover}\" class=\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\" col-index=\"renderIndex\" title=\"TOOLTIP\">\n"
		+ "    <div class=\"media\">\n"
		+ "     <div class=\"media-left media-middle required\" style=\"padding-right:2px\" ng-if=\"col.colDef.isRequired\"></div>\n"
		+ "     <div class=\"media-body media-middle\">\n"
		+ "        <span class=\"ui-grid-header-cell-label\" ui-grid-one-bind-id-grid=\"col.uid + '-header-text'\">\n"
		+ "            <span>{{ col.displayName CUSTOM_FILTERS }}</span>\n"
		+ "        </span> \n"
		+ "     </div>\n"
		+ "     <div class=\"media-right media-middle\" ng-if=\"col.sort.direction\">\n"
		+ "        <span>\n"
		+ "           <i class=\"icon icon-up_1\" ng-class=\"{ 'active': col.sort.direction == asc, 'disable': !col.sort.direction }\" aria-hidden=\"true\"></i> \n"
		+ "           <i class=\"icon icon-down_1\" ng-class=\"{ 'active': col.sort.direction == desc, 'disable': !col.sort.direction }\" aria-hidden=\"true\"></i> \n"
		+ "        </span>\n"
		+ "     </div>\n"
		+ "    </div>\n"
		+ "    </div>\n"
		+ "    <div role=\"button\" tabindex=\"0\" ui-grid-one-bind-id-grid=\"col.uid + '-menu-button'\" class=\"ui-grid-column-menu-button\" ng-if=\"grid.options.enableColumnMenus && !col.isRowHeader  && col.colDef.enableColumnMenu !== false\" ng-click=\"toggleMenu($event)\" ng-keydown=\"headerCellArrowKeyDown($event)\" ui-grid-one-bind-aria-label=\"i18n.headerCell.aria.columnMenuButtonLabel\" aria-haspopup=\"true\">\n"
		+ "        <i class=\"ui-grid-icon-angle-down\" aria-hidden=\"true\">&nbsp;</i>\n"
		+ "    </div>\n"
		+ "    <div ui-grid-filter></div>\n"
		+ "</div>"
	);
	
	$templateCache.put('ui-grid/uiGridViewport',''
		+ '<div role="rowgroup" class="ui-grid-viewport" ng-style="colContainer.getViewportStyle()">\n'
		+ '<div ui-grid-customer-scrollbar on-scroll="scrollHandler" refresh-on-change="rowContainer.renderedRows" wheel-propagation="true" class="scroller">\n'
		+ "    <!-- tbody -->\n"
		+ '    <div class="ui-grid-canvas">\n'
		+ '        <div ng-form="rowForm{{side ? rowRenderIndex : \'Entity\'+rowRenderIndex}}" ng-repeat="(rowRenderIndex, row) in rowContainer.renderedRows" class="ui-grid-row" ng-style="Viewport.rowStyle(rowRenderIndex)">'
		+ '            <div role="row" class="grid-row" ui-grid-row="row" ng-mouseover="row._hover=true" ng-mouseleave="row._hover=false"'
		+ '                ng-class="{\'selected-row\':row.isSelected,'
		+ '                           \'hover-row\':row._hover, '
		+ '                           \'created-row\':row.compareResult.isCreated,'
		+ '                           \'deleted-row\':row.compareResult.isDeleted,'
		+ '                           \'updated-row\':row.compareResult.isUpdated}" row-render-index="rowRenderIndex" '
		+ '                fs-ui-grid-compare="row.grid.options.verifyData" fs-ui-grid="grid" fs-ui-grid-row="row" fs-ui-grid-col="col"></div>'
		+ '         </div>'
		+ '    </div>'
		+ '</div>'
		+ '</div>'
	);
	
	$templateCache.put('ui-grid/uiGridCell', ''
		+ '<div class="ui-grid-cell-contents" ng-class="{\'updated-cell\': row.compareResult.fields[col.colDef.model].hasChanged}" title="TOOLTIP"'
		+ '  ng-style="{\'text-align\':col.colDef.textAlign || \'left\'}"'
		+ '  uib-tooltip-template="\'fs/layout/template/uiGrid/tooltipTpl.html\'"'
		+ '  tooltip-enable="(row.compareResult.columns[col.colDef.model].tooltipMessage && row.compareResult.columns[col.colDef.model].tooltipMessage.length > 0) || (col.colDef.tooltip && col.colDef.tooltip.length > 0)"'
		+ '  tooltip-class="{{col.colDef.tooltipClass}}" '
		+ '  tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="true" '
		+ '  tooltip-placement="{{col.colDef.tooltipPlacement}}">'
		+ '    <span>{{COL_FIELD CUSTOM_FILTERS}}</span>'
		+ ' </div>'
	);
	
	$templateCache.put('ui-grid/ui-grid', ""
		+ "<div ui-i18n=\"en\" class=\"ui-grid\" ng-class=\"{'enable-grid-menu':grid.options.enableGridMenu}\"><!-- TODO (c0bra): add \"scoped\" attr here, eventually? -->\n"
		+ "    <style ui-grid-style>\n"
		+ "    .grid{{ grid.id }} {\n" 
		+ "        /* Styles for the grid */\n" 
		+ "    }\n" +
		+ "    .grid{{ grid.id }} .ui-grid-row, \n"
		+ "    .grid{{ grid.id }} .ui-grid-cell, \n"
		+ "    .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {\n" 
		+ "        min-height: {{ grid.options.rowHeight }}px;\n" 
		+ "    }\n" 
		+ "    .grid{{ grid.id }} .ui-grid-row:last-child .ui-grid-cell {\n" 
		+ "        border-bottom-width: {{ (((grid.getVisibleRowCount() * grid.options.rowHeight) < grid.getViewportHeight()) && '1px') || '0' }};\n" 
		+ "    }\n" 
		+ "\n" 
		+ "    {{ grid.verticalScrollbarStyles }}\n" 
		+ "    {{ grid.horizontalScrollbarStyles }}\n" 
		+ "\n" 
		+ "    /*\n" 
		+ "    .ui-grid[dir=rtl] .ui-grid-viewport {\n" 
		+ "        padding-left: {{ grid.verticalScrollbarWidth }}px;\n"
		+ "    }\n" 
		+ "    */\n" 
		+ "    \n" 
		+ "    {{ grid.customStyles }}\n"
		+ "\n" 
		+ "    </style>\n"
		+ "    <div class=\"ui-grid-contents-wrapper\" role=\"grid\">\n"
		+ "        <div ui-grid-menu-customer-button ng-if=\"grid.options.enableGridMenu\"></div>\n"
		+ "        <div ng-if=\"grid.hasLeftContainer()\" style=\"width: 0\" ui-grid-pinned-container=\"'left'\" class=\"oprationContainer\"></div>\n"
		+ "        <div ui-grid-render-container container-id=\"'body'\" col-container-name=\"'body'\" row-container-name=\"'body'\" bind-scroll-horizontal=\"true\" bind-scroll-vertical=\"true\"\n"
		+ "            enable-horizontal-scrollbar=\"grid.options.enableHorizontalScrollbar\" \n"
		+ "            enable-vertical-scrollbar=\"grid.options.enableVerticalScrollbar\"></div>\n"
		+ "        <div ng-if=\"grid.hasRightContainer()\" style=\"width: 0\" ui-grid-pinned-container=\"'right'\" class=\"oprationContainer\"></div>\n"
		+ "        <div ui-grid-grid-footer ng-if=\"grid.options.showGridFooter\" class=\"gridFooterbox clearfix\"></div>\n"
		+ "        <div ui-grid-column-menu ng-if=\"grid.options.enableColumnMenus\" style=\"z-index:1000\"></div>\n"
		+ "        <div ng-transclude></div>\n"
		+ "    </div>\n"
		+ "</div>"
	);
	
	$templateCache.put('ui-grid/ui-grid-menu-button', ""
		+ "<div class=\"ui-grid-menu-button\">\n"
		+ "  <div class=\"media\">\n"
		+ "    <div class=\"switch media-body media-middle\">"
		+ "      <input type=\"checkbox\" id=\"switch{{grid.id}}\" ng-model=\"switchChecked\" class=\"switch-checkbox\" ng-checked=\"grid.options.displayStyle == 'all'\" ng-click=\"toggleDisplayStyle()\">"
		+ "      <label class=\"switch-label\" for=\"switch{{grid.id}}\">"
		+ "        <span class=\"switch-inner\" data-all=\"{{'grid.label.showall' | translate}}\" data-normal=\"{{'grid.label.normal' | translate}}\"></span>"
		+ "        <span class=\"switch-icon\"></span>"
		+ "      </label>"
		+ "    </div>"
		+ "    <div role=\"button\" ui-grid-one-bind-id-grid=\"'grid-menu'\" class=\"ui-grid-icon-container media-right media-middle\" ng-click=\"toggleMenu()\" aria-haspopup=\"true\">\n"
		+ "        <i class=\"ui-grid-icon-menu\"></i>\n"
		+ "    </div>\n"
		+ "  </div>"
		+ "  <div ui-grid-menu menu-items=\"menuItems\"></div>\n"
		+ "</div>"
	);
	
	$templateCache.put('ui-grid/uiGridMenu', ""
		+ "<div class=\"ui-grid-menu\" ng-show=\"shown\">\n"
		/*+ "    <style ui-grid-style>{{dynamicStyles}}</style>\n"*/
		+ "    <div class=\"ui-grid-menu-mid\" ng-show=\"shownMid\">\n"
		+ "        <div class=\"ui-grid-menu-inner\" ng-if=\"shown\">\n"
		+ "            <ul role=\"menu\" class=\"ui-grid-menu-items\">\n"
		+ "                <li><h4>{{'grid.label.customize'|translate}}:</h4></li>\n"
		+ "                <li ng-repeat=\"item in menuItems\" ng-click=\"$event.stopPropagation();\" ng-if=\"item.context && item.context.gridCol\" role=\"menuitem\" ui-grid-customer-menu-item ui-grid-one-bind-id=\"'menuitem-'+$index\"action=\"item.action\" name=\"item.title\" active=\"item.active\" icon=\"item.icon\" shown=\"item.shown\" context=\"item.context\" template-url=\"item.templateUrl\" leave-open=\"item.leaveOpen\" index=\"$index\" screen-reader-only=\"item.screenReaderOnly\"></li>\n"
		+ "            </ul>\n"
		+ "        </div>\n"
		+ "    </div>\n"
		+ "</div>"
	);


	$templateCache.put('ui-grid/uiGridMenuItem', ""
		+ "<div class=\"ui-grid-menu-item\" ng-focus=\"focus=true\" ng-blur=\"focus=false\" ng-show=\"itemShown() && action\">\n"
		+ "    <input id=\"{{getGrid().id+''+index}}\" type=\"checkbox\" ng-model=\"visible\" ng-click=\"itemAction($event, title)\" ng-checked=\"visible != false\"/>"
		+"     <label for=\"{{getGrid().id+''+index}}\" style=\"cursor: pointer;\" >{{ label() }}</label>"
		+ "</div>"
	);
	
	$templateCache.put('ui-grid/uiGridRenderContainer', "" 
		+ "<div role=\"presentation\" ui-grid-one-bind-id-grid=\"'grid-container'\" class=\"ui-grid-render-container\" ng-style=\"{ 'margin-left': colContainer.getMargin('left') + 'px', 'margin-right': colContainer.getMargin('right') + 'px' }\">\n" 
		+ "    <!-- All of these dom elements are replaced in place -->\n" 
		+ "    <div ui-grid-header></div>\n" 
		+ "    <div ui-grid-viewport></div>\n" 
		+ "    <div ng-if=\"colContainer.needsHScrollbarPlaceholder()\" class=\"ui-grid-scrollbar-placeholder\" ng-style=\"{height:colContainer.grid.scrollbarHeight + 'px'}\"></div>\n" 
		+ "    <ui-grid-footer ng-if=\"grid.options.showColumnFooter\"></ui-grid-footer>\n" 
		+ "</div>" );
	
	$templateCache.put('ui-grid/ui-grid-footer', ""
		    + "<div class=\"ui-grid-footer-panel ui-grid-footer-aggregates-row\">\n"
		    + "    <!-- tfooter -->\n"
		    + "    <div class=\"ui-grid-footer ui-grid-footer-viewport\">\n"
		    + "        <div class=\"ui-grid-footer-canvas\">\n"
		    + "            <div class=\"ui-grid-footer-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\">\n"
		    + "                <div role=\"row\" class=\"ui-grid-footer-cell-row\">\n"
		    + "                    <div role=\"gridcell\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" col=\"col\" render-index=\"$index\" class=\"ui-grid-footer-cell ui-grid-clearfix\">\n"
		    + "                        <div class=\"operationHeaderButtons\" ng-if=\"col.colDef.name == 'operationRowHeaderCol' && col.grid.options.__addRow\">\n"
		    + '                            <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationAdd" ng-click="addTooltipIsOpen=false;col.grid.options.__addRow($event)"'
			+ '                                tooltip-is-open="addTooltipIsOpen" uib-tooltip="{{\'label.global.add\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
			+ '    	                           <span class="icon icon-add_1"></span>'
			+ '                            </button>'
		    + "                         </div>"
		    + "                    </div>\n"
		    + "                </div>\n"
		    + "            </div>\n"
		    + "        </div>\n"
		    + "    </div>\n"
		    + "</div>"
		  );
	
	$templateCache.put('ui-grid/emptyBaseLayerContainer', '');
	
	 $templateCache.put('ui-grid/columnResizer',
		"<div ui-grid-customer-column-resizer ng-if=\"grid.options.enableColumnResizing && !grid.options.disableColumnResize\" class=\"ui-grid-column-resizer\" col=\"col\" position=\"right\" render-index=\"renderIndex\" unselectable=\"on\"></div>"
	 );
	
	/*
	 * $templateCache.put('ui-grid/ui-grid-header', "" + "<div role=\"rowgroup\" class=\"ui-grid-header\">\n" + " <!-- theader -->\n" + " <div class=\"ui-grid-top-panel\">\n" + " <div
	 * class=\"ui-grid-header-viewport\">\n" + " <div class=\"ui-grid-header-canvas\">\n" + " <div class=\"ui-grid-header-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\">\n" + " <div
	 * role=\"row\" class=\"ui-grid-header-cell-row\">\n" + " <div class=\"ui-grid-header-cell ui-grid-clearfix\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" ui-grid-header-cell
	 * col=\"col\" render-index=\"$index\"></div>\n" + " </div>\n" + " </div>\n" + " </div>\n" + " </div>\n" + " </div>\n" + "</div>" );
	 * 
	 * $templateCache.put('ui-grid/uiGridHeaderCell', "" + "<div role=\"columnheader\" ng-class=\"{ 'sortable': sortable, 'ui-grid-header-cell-last-col': isLastCol }\"
	 * ui-grid-one-bind-aria-labelledby-grid=\"col.uid + '-header-text ' + col.uid + '-sortdir-text'\" aria-sort=\"{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ?
	 * 'descending' : (!col.sort.direction ? 'none' : 'other'))}}\">\n" + " <div role=\"button\" tabindex=\"0\" ng-keydown=\"handleKeyDown($event)\" class=\"ui-grid-cell-contents
	 * ui-grid-header-cell-primary-focus\" col-index=\"renderIndex\" title=\"TOOLTIP\">\n" + " <span class=\"ui-grid-header-cell-label\" ui-grid-one-bind-id-grid=\"col.uid + '-header-text'\">{{
	 * col.displayName CUSTOM_FILTERS }}</span> \n" + " <span ui-grid-one-bind-id-grid=\"col.uid + '-sortdir-text'\" ui-grid-visible=\"col.sort.direction\"
	 * aria-label=\"{{getSortDirectionAriaLabel()}}\">\n" + " <i ng-class=\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc,
	 * 'ui-grid-icon-blank': !col.sort.direction }\" title=\"{{isSortPriorityVisible() ? i18n.headerCell.priority + ' ' + ( col.sort.priority + 1 ) : null}}\" aria-hidden=\"true\"></i> \n" + " <sub
	 * ui-grid-visible=\"isSortPriorityVisible()\" class=\"ui-grid-sort-priority-number\">{{col.sort.priority + 1}}</sub>\n" + " </span>\n" + " </div>\n" + " <div role=\"button\" tabindex=\"0\"
	 * ui-grid-one-bind-id-grid=\"col.uid + '-menu-button'\" class=\"ui-grid-column-menu-button\" ng-if=\"grid.options.enableColumnMenus && !col.isRowHeader && col.colDef.enableColumnMenu !== false\"
	 * ng-click=\"toggleMenu($event)\" ng-keydown=\"headerCellArrowKeyDown($event)\" ui-grid-one-bind-aria-label=\"i18n.headerCell.aria.columnMenuButtonLabel\" aria-haspopup=\"true\">\n" + " <i
	 * class=\"ui-grid-icon-angle-down\" aria-hidden=\"true\">&nbsp;</i>\n" + " </div>\n" + " <div ui-grid-filter></div>\n" + "</div>" );
	 * 
	 * $templateCache.put('ui-grid/ui-grid-row', "" + "<div ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.uid\"" + " ui-grid-one-bind-id-grid=\"rowRenderIndex + '-' +
	 * col.uid + '-cell'\" class=\"ui-grid-cell\"" + " ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" " + " role=\"{{col.isRowHeader ? 'rowheader' : 'gridcell'}}\"" + " ui-grid-cell>\n" +"</div>" );
	 */
}